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

ASP.NET Core 2.2.1 Hosting - HostForLIFE.eu :: Deleting Files With Events

clock August 8, 2018 09:12 by author Peter

While working on the dotNetTips Dev Cleaner utility, I wanted to make the deletion of files even faster. While writing this utility I found and worked on speed issues, almost all relating to updating the user interface. So to decouple the deleting from the UI, I decided to add a new feature to the dotNetTips.Utility open source project.

Processor Class
I added a new class in the dotNetTips.Utility.IO namespace called Processor. The purpose of this class is to copy, move and delete files while firing events that can be used to update the UI. Unlike other methods I have used in other frameworks if an exception occurs, it fires an event and keeps processing.

First I created the event,
public event EventHandler<ProgressEventArgs> Processed; 
 
protected virtual void OnProcessed(ProgressEventArgs e) 

EventHandler<ProgressEventArgs> processedEvent = this.ProcessedEvent; 
if (processedEvent != null) 

processedEvent(this, e); 

}  

//The event above is called by the code below: 

public int DeleteFiles(IEnumerable<FileInfo> files) 

    Encapsulation.TryValidateParam(files, "files", ""); 
    int result = 0; 
    IEnumerator<FileInfo> enumerator; 
    try 
    { 
        enumerator = files.AsParallel<FileInfo>().GetEnumerator(); 
        while (enumerator.MoveNext()) 
        { 
            FileInfo current = enumerator.Current; 
            if (current.Exists) 
            { 
                try 
                { 
                    current.Delete(); 
                    result++; 
                    ProgressEventArgs e = new ProgressEventArgs(); 
                    e.Name = current.FullName; 
                    e.ProgressState = ProgressState.Deleted; 
                    e.Size = current.Length; 
                    this.OnProcessed(e); 
                    continue; 
                } 
                catch (Exception ex) 
                { 
                    ProjectData.SetProjectError(ex); 
                    ProgressEventArgs e1 = new ProgressEventArgs(); 
                    e1.Name = current.FullName; 
                    e1.ProgressState = ProgressState.Error; 
                    e1.Size = current.Length; 
                    e1.Message = ex.Message; 
                    this.OnProcessed(e1); 
                    ProjectData.ClearProjectError(); 
                    continue; 
                } 
            } 

            ProgressEventArgs e2 = new ProgressEventArgs(); 
            e2.Name = current.FullName; 
            e2.ProgressState = ProgressState.Error; 
            e2.Size = current.Length; 
            e2.Message = Resources.FileNotFound; 
            this.OnProcessed(e2); 
        } 
    } 
    finally 
    { 
        if (enumerator != null) 
        { 
            enumerator.Dispose(); 
        } 
    } 

    return result; 


This new class helped my utility go from deleting 1K files per second to up to around 2K per second!

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

 



ASP.NET Core 2.2.1 Hosting - HostForLIFE.eu :: How To Create And Download Zipped Files In .NET?

clock August 6, 2018 11:07 by author Peter

Have you ever encountered a scenario when you have to download a few files zipped and compressed? Few developments involving the manipulation of documents and its management would require this. There are a lot of packages out in the market. Here, in this article, I would be sharing the use of DotNetZip package used to zip, unzip & compress files using C#, VB.NET, & any .NET language.

Download the DotNetzip package from NuGet package.

Once downloaded, it's all set to use the DotNetzip package to start zipping the files and compressing them. For the files to be zipped, here I will be using the file path and select each file to be zipped. Here also, we will see how a file is created on the fly (a PDF using Rotativa) is saved in the same folder and zipped.

File created on the fly using Rotativa
var pdfResult = new Rotativa.PartialViewAsPdf("~/Template.cshtml", model) //This is HTML that would be generated as PDF  
{  
    FileName = "Template.pdf"  
};  
var resultSet = pdfResult.BuildPdf(ControllerContext);  
if (resultSet != null) {  
    string path = Path.Combine(Server.MapPath(subPath));  
    FileStream fs = new FileStream(path + ".pdf", FileMode.Create, FileAccess.ReadWrite);  
    BinaryWriter bw = new BinaryWriter(fs);  
    bw.Write(resultSet);  
    bw.Close();  
}  


The above code snippet is generating a PDF using a cshtml Razor View page using Rotativa Using Rotativa Best to follow the mentioned article for more information to generate PDF using Rotativa using MVC. Let's look at the code snippet for zipping.

using(ZipFile zipFile = new ZipFile()) {  
    //Get all filepath from folder  
    String[] files = Directory.GetFiles(Server.MapPath("/"));  
    string fileUniqueName = "Template"  
    foreach(string file in files) {  
        if (file.Contains(fileUniqueName.ToString())) {  
            zipFile.AddFile(file, @ "TemplateDocs_" + DateTime.Now);  
            //Adding files from filepath into Zip  
        }  
    }  
    Response.ClearContent();  
    Response.ClearHeaders();  
    //Set zip file name  
    Response.AppendHeader("content-disposition", "attachment; filename=TemplatedDocuments.zip");  
    zipFile.CompressionMethod = CompressionMethod.BZip2;  
    zipFile.CompressionLevel = Ionic.Zlib.CompressionLevel.BestCompression;  
    //Save the zip content in output stream  
    zipFile.Save(outputStream);  
}  
//Set the cursor to start position  
outputStream.Position = 0;  
String[] filesToDelete = Directory.GetFiles(Server.MapPath("/"));  
foreach(string file in filesToDelete) {  
    if (file.Contains(fileUniqueName.ToString())) {  
        FileInfo fi = new FileInfo(file);  
        fi.Delete();  
    }  
}  
return new FileStreamResult(outputStream, fileType);  


The above snippet is just required to start zipping and compressing the files. As you can see using block for the ZipFile is created with instantiation of its object.

Then, the files present under the path are navigated using Server.MapPath(""), Once the path is set, the files if with some unique string character in the filename needs to be searched and only zipped, is set to a variable.

Then each file is looped through and added to the ZipFile object, here zipFile.AddFiles(file, ZippedFolderName); ZipFolderName here is the name you set for the folder having all the files after extraction.

There are three compression levels for the ZipFile an enum which describes through code as below,
public enum CompressionMethod {  
    //  
    // Summary:  
    // No compression at all. For COM environments, the value is 0 (zero).  
    None = 0,  

        Deflate = 8,  
        
        BZip2 = 12  
}  


The above are the three algorithms used. I personally have used only BZip2 based on few good reviews.

Once compressed and all files inserted into the folder, the zipped folder is ready to be downloaded using the FileStreamResult in MVC action.

This is the simple explanation and the code snippet for the Zip file concept. This is simple and really handy to be used and it also provides the compression algorithms which are good to go with.

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



ASP.NET Core 2.2.1 Hosting - HostForLIFE.eu :: Pass Data To ASP.NET Web Service (ASMX) From Cross-Origin

clock July 30, 2018 11:15 by author Peter

In this blog, we are going to create a “Hello World” ASP.Net Web Service (ASMX) with parameters, and allow a request from cross-origin. Now, here we implement ASP.Net Web Service from Visual Studio 2017. We have created an empty ASP.Net Web Application solution and added “demo.asmx” in solution. Then, added code for “HelloWorld” method with “name” parameter as mention below snippet,
    [WebMethod] 
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)] 
    public string HelloWorld(string text) { 
        return "Hello World " + text; 
    } 

We will invoke this web service using HTTP verb. So, we defined “ScriptMethodAttribute” for setting response format JSON.

We need to enable script service to invoke & pass parameters in Web Service from the script as shown in the below screenshot:

Then set demo.asmx as the startup page and run/test this web service on IIS:

Below is the example of “HelloWorld” webservice:
 

Now, we will create another ASP.NET web application which will have index.html to request “Hello world” web service using jQuery,
$.ajax({ 
    type: "POST", 
    url: "http://localhost:50555/Demo.asmx/HelloWorld", 
    data: { 
        'text': ' Peter' 
    }, 
    success: function(data) { 
        console.log(data); 
    }, 
    error: function(request, status, error) { 
        console.log(request); 
    } 
}); 


We will receive this error message: “No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:11111' is therefore not allowed access.”

To solve the above error we will need to add the following code under configuration node in web.config,
<system.webServer> 
    <httpProtocol> 
        <customHeaders> 
            <add name="Access-Control-Allow-Headers" value="accept, content-type" /> 
            <add name="Access-Control-Allow-Origin" value="http://localhost:11111" /> 
            <add name="Access-Control-Allow-Methods" value="POST, GET, OPTIONS" /> 
        </customHeaders> 
    </httpProtocol> 
</system.webServer> 

Now, when we request this web service, it will successfully return and the response of the web service is as below in the console:

We have learned about passing data to ASP.NET Web Service (ASMX) from Cross-Origin.

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



ASP.NET Core 2.2.1 Hosting - HostForLIFE.eu :: Command Design Pattern In C# .NET

clock July 25, 2018 09:42 by author Peter

Command Design Pattern is a type of Behavioral Design Pattern.

Behavioral Design Pattern
It's about object communication, their responsibilities, and how they communicate to each other.

There might be a situation where we want to encapsulate the required information in an Object to perform some task and the task can be performed many times or whenever it's required. The command design pattern is the solution. It also gives you an easy way to implement Undo() that can just undo multiple commands.

  • Implementation - Typically, Implementation of Command Pattern is divided into 4 parts.
  • Command - That executes an action.
  • Receiver - Objects that receive the action from the command.

Invoker: Invoke the Commands to execute their actions. The Invoker may be a queue that holds commands for future execution, or holds such commands which can be used by different applications. The machine can be used to execute commands multiple times or can be used to undo the command.

Client
Client is the main program that asks for a command to be executed.
Consider the case of a banking application which is capable of making transactions i.e. Transfer, Deposit, Withdraw etc.
Let's identify each part of the command design pattern we discussed above.
Account of a customer ? Think, what it should be ?
Command ? Read command's definition again.......It says that it executes an action, but what action Account will it execute? Actions such as increment in account balance or decrements in account balance can be executed on Account by the Commands Deposit/Withdraw . So, if it receives actions, it means account is a Receiver.

So, Receiver is Account, and Command Deposit will add money from Account Balance and Withdraw command will subtract money from Account Balance.
/// <summary> 
/// Reciever of Command 
/// </summary> 
public class Account { 
    public string CustomerName { 
        get; 
        set; 
    } 
    public double AccountBalance { 
        get; 
        set; 
    } 
    public Account(string customerName, double accountBalance) { 
        CustomerName = customerName; 
        AccountBalance = accountBalance; 
    } 

/// <summary> 
/// Defines the action of Command those can be executed - will be called by Invoker 
/// IsCommandCompleted signals the command is completed and can be removed from Invoker 
/// </summary> 
public interface ITransaction { 
    void ExecuteCommand(); 
    bool IsCommandCompleted { 
        get; 
        set; 
    } 

/// <summary> 
/// Deposit Command 
/// </summary> 
public class Deposit: ITransaction { 
    private readonly Account _account; 
    private readonly double _amount; 
    public bool IsCommandCompleted { 
        get; 
        set; 
    } 
    public Deposit(Account account, double amount) { 
        _account = account; 
        _amount = amount; 
        IsCommandCompleted = false; 
    } 
    public void ExecuteCommand() { 
        _account.AccountBalance += _amount; 
        IsCommandCompleted = true; 
    } 

/// <summary> 
/// Withdraw Command 
/// </summary> 
public class Withdraw: ITransaction { 
    private readonly Account _account; 
    private readonly double _amount; 
    public bool IsCommandCompleted { 
        get; 
        set; 
    } 
    public Withdraw(Account account, double amount) { 
        _account = account; 
        _amount = amount; 
        IsCommandCompleted = false; 
    } 
    public void ExecuteCommand() { 
        if (_account.AccountBalance >= _amount) { 
            _account.AccountBalance -= _amount; 
            IsCommandCompleted = true; 
        } 
    } 

/// <summary> 
/// Transfer Command 
/// </summary> 
public class Transfer: ITransaction { 
        private readonly Account _fromAccount; 
        private readonly Account _toAccount; 
        private readonly double _amount; 
        public bool IsCommandCompleted { 
            get; 
            set; 
        } 
        public Transfer(Account fromAccount, Account toAccount, double amount) { 
            _fromAccount = fromAccount; 
            _toAccount = toAccount; 
            IsCommandCompleted = false; 
        } 
        public void ExecuteCommand() { 
            _fromAccount.AccountBalance -= _amount; 
            _toAccount.AccountBalance += _amount; 
            IsCommandCompleted = true; 
        } 


Lets write Invoker,
public class TransactionManager { 
    private readonly IList < ITransaction > _transactions = new List < ITransaction > (); 
    public bool HasInCompleteTransactions { 
        get { 
            return _transactions.Any(x => !x.IsCommandCompleted); 
        } 
    } 
    public IList < ITransaction > GetPendingTransactions() { 
        return _transactions ? .Where(x => !x.IsCommandCompleted) ? .ToList(); 
    } 
    public void AddTransaction(ITransaction transaction) { 
        _transactions.Add(transaction); 
    } 
    public void ProcessPendingTransactions() { 
        foreach(var transaction in _transactions.Where(x => !x.IsCommandCompleted)) { 
            transaction.ExecuteCommand(); 
        } 
    } 



The Client is responsible to create commands and pass them to the Invoker. The Commands will be held in the _transactions list, until the Client calls ProcessInCompleteTransactions. Then, the Invoker will try to execute each incomplete Command.

Invoker should not be aware of anything about what the Command can do, or what inputs it needs. All it needs to know is that the Command should be executed.

We will here simulate the client using our Console application to demonstrate.
class Program { 
    static void Main(string[] args) { 
        //Add 100 to the account - there should not be any pending job 
        TransactionManager manager = new CommandPattern.TransactionManager(); 
        Account accountAshish = new CommandPattern.Account("Ashish", 0); 
        ITransaction depositTransaction = new Deposit(accountAshish, 100); 
        manager.AddTransaction(depositTransaction); 
        manager.ProcessPendingTransactions(); 
        //try to withdraw 200 - transction will be pending since the balance is account is low 
        ITransaction withdrawTransaction = new Withdraw(accountAshish, 200); 
        manager.AddTransaction(withdrawTransaction); 
        manager.ProcessPendingTransactions(); 
        var pendingTransaction = manager.HasInCompleteTransactions; 
        Console.WriteLine(pendingTransaction); 
        Console.ReadKey(); 
        //add 200- still withdraw trasaction would be pending since we are adding money after withdraw failed attempt, 
        //we would need to execute failed transacction again 
        ITransaction anotherDepositTransaction = new Deposit(accountAshish, 200); 
        manager.AddTransaction(anotherDepositTransaction); 
        manager.ProcessPendingTransactions(); 
        Console.WriteLine(manager.HasInCompleteTransactions); 
        Console.ReadKey(); 
        if (manager.HasInCompleteTransactions) { 
            //reattempt failed transactions 
            ReattemptPendingTransactions(manager); 
        } 
        Console.WriteLine(manager.HasInCompleteTransactions); 
        Console.ReadKey(); 
        //Try Transfer 
        Account accountAvinash = new Account("Avinash", 10); 
        ITransaction transferTransaction = new Transfer(accountAshish, accountAvinash, 10); 
        manager.AddTransaction(transferTransaction); 
        manager.ProcessPendingTransactions(); 
        Console.WriteLine("Ashish account balance:" + accountAshish.AccountBalance); 
        Console.WriteLine("Anjali account balance:" + accountAvinash.AccountBalance); 
        Console.ReadKey(); 
    } 
    private static void ReattemptPendingTransactions(TransactionManager manager) { 
        var pendingTransactions = manager.GetPendingTransactions(); 
        foreach(var item in pendingTransactions) { 
            item.ExecuteCommand(); 
        } 
    } 


Enhancement Undo
Suppose you want to undo the command. Modify your code, add Undo in your command.

You should facilitate your program with the undo all command and undo a particular command. In case of a particular command undo, you would need some kind of identifier which can uniquely identify the command (i.e. Id) and perform undo on it. We should be able to Undo successful commands also, we can have some status of command which tells us if command is executed successfully or not, unprocessed, Undo Successful, Undo Failed etc.

Transaction would look like,
public interface ITransaction { 
    int Id { 
        get; 
        set; 
    } 
    void ExecuteCommand(); 
    bool IsCommandCompleted { 
        get; 
        set; 
    } 
    void Undo(); 


Implement modified interface in all the Commands Deposit, Withdraw and Transfer

Create an enum to set Command state
/// <summary> 
/// Command sate enum 
/// </summary> 
public enum CommandState { 
    UnProcessed, 
    ExecutionFailed, 
    ExecutionSuccessed, 
    UndoDone, 
    UndoFailed 

public interface ITransaction { 
    int Id { 
        get; 
        set; 
    } 
    void ExecuteCommand(); 
    bool IsCommandCompleted { 
        get; 
        set; 
    } 
    CommandState Status { 
        get; 
        set; 
    } 
    void Undo(); 
} === === === === === == Other Updated Classes === === === === === === === === === === === == private static void ReattemptPendingTransactions(TransactionManager manager) { 
    var pendingTransactions = manager.GetPendingTransactions(); 
    foreach(var item in pendingTransactions) { 
        item.ExecuteCommand(); 
    } 


/// <summary> 
/// Reciever of Command 
/// </summary> 
public class Account { 
    public string CustomerName { 
        get; 
        set; 
    } 
    public double AccountBalance { 
        get; 
        set; 
    } 
    public Account(string customerName, double accountBalance) { 
        CustomerName = customerName; 
        AccountBalance = accountBalance; 
    } 

/// <summary> 
/// Defines the action of Command those can be executed - will be called by Invoker 
/// IsCommandCompleted signals the command is completed and can be removed from Invoker 
/// </summary> 
public interface ITransaction { 
    int Id { 
        get; 
        set; 
    } 
    void ExecuteCommand(); 
    bool IsCommandCompleted { 
        get; 
        set; 
    } 
    CommandState Status { 
        get; 
        set; 
    } 
    void Undo(); 

/// <summary> 
/// Command sate enum 
/// </summary> 
public enum CommandState { 
    UnProcessed, 
    ExecutionFailed, 
    ExecutionSuccessed, 
    UndoDone, 
    UndoFailed 

/// <summary> 
/// Deposit Command 
/// </summary> 
public class Deposit: ITransaction { 
    private readonly Account _account; 
    private readonly double _amount; 
    public bool IsCommandCompleted { 
        get; 
        set; 
    } 
    public int Id { 
        get; 
        set; 
    } 
    public CommandState Status { 
        get { 
            throw new NotImplementedException(); 
        } 
        set { 
            throw new NotImplementedException(); 
        } 
    } 
    public Deposit(int Id, Account account, double amount) { 
        this.Id = Id; 
        _account = account; 
        _amount = amount; 
        IsCommandCompleted = false; 
        Status = CommandState.UnProcessed; 
    } 
    public void ExecuteCommand() { 
        _account.AccountBalance += _amount; 
        IsCommandCompleted = true; 
        Status = CommandState.ExecutionSuccessed; 
    } 
    public void Undo() { 
        if (_account.AccountBalance >= _amount) { 
            _account.AccountBalance -= _amount; 
            Status = CommandState.UndoDone; 
        } else { 
            Status = CommandState.UndoFailed; 
        } 
    } 

/// <summary> 
/// Withdraw Command 
/// </summary> 
public class Withdraw: ITransaction { 
    private readonly Account _account; 
    private readonly double _amount; 
    public bool IsCommandCompleted { 
        get; 
        set; 
    } 
    public int Id { 
        get; 
        set; 
    } 
    public CommandState Status { 
        get; 
        set; 
    } 
    public Withdraw(int Id, Account account, double amount) { 
        _account = account; 
        _amount = amount; 
        IsCommandCompleted = false; 
        this.Id = Id; 
        Status = CommandState.UnProcessed; 
    } 
    public void ExecuteCommand() { 
        if (_account.AccountBalance >= _amount) { 
            _account.AccountBalance -= _amount; 
            IsCommandCompleted = true; 
            Status = CommandState.ExecutionSuccessed; 
        } else { 
            Status = CommandState.ExecutionFailed; 
        } 
    } 
    public void Undo() { 
        _account.AccountBalance += _amount; 
        Status = CommandState.UndoDone; 
    } 

/// <summary> 
/// Transfer Command 
/// </summary> 
public class Transfer: ITransaction { 
    private readonly Account _fromAccount; 
    private readonly Account _toAccount; 
    private readonly double _amount; 
    public bool IsCommandCompleted { 
        get; 
        set; 
    } 
    public int Id { 
        get; 
        set; 
    } 
    public CommandState Status { 
        get; 
        set; 
    } 
    public Transfer(int Id, Account fromAccount, Account toAccount, double amount) { 
        _fromAccount = fromAccount; 
        _toAccount = toAccount; 
        IsCommandCompleted = false; 
        _amount = amount; 
        this.Id = Id; 
        Status = CommandState.UnProcessed; 
    } 
    public void ExecuteCommand() { 
        if (_fromAccount.AccountBalance >= +_amount) { 
            _fromAccount.AccountBalance -= _amount; 
            _toAccount.AccountBalance += _amount; 
            IsCommandCompleted = true; 
            Status = CommandState.ExecutionSuccessed; 
        } else { 
            Status = CommandState.ExecutionFailed; 
        } 
    } 
    public void Undo() { 
        if (_toAccount.AccountBalance >= _amount) { 
            _toAccount.AccountBalance -= _amount; 
            _fromAccount.AccountBalance += _amount; 
            Status = CommandState.UndoDone; 
        } else { 
            Status = CommandState.UndoFailed; 
        } 
    } 

public class TransactionManager { 
    private readonly IList < ITransaction > _transactions = new List < ITransaction > (); 
    public bool HasInCompleteTransactions { 
        get { 
            return _transactions.Any(x => !x.IsCommandCompleted); 
        } 
    } 
    public IList < ITransaction > GetPendingTransactions() { 
        return _transactions ? .Where(x => !x.IsCommandCompleted) ? .ToList(); 
    } 
    public void AddTransaction(ITransaction transaction) { 
        _transactions.Add(transaction); 
    } 
    public void ProcessPendingTransactions() { 
        foreach(var transaction in _transactions.Where(x => !x.IsCommandCompleted)) { 
            transaction.ExecuteCommand(); 
        } 
    } 


Note
I won't create a client for these extended functionalities, I want you to try this. If you find any difficulty, please reach out to me through the Contact Us Page.

Command Design Pattern is often used with message queue applications such as, logging. In case of sudden system shut down/ crash, our system would be able read the incomplete commands from the queue, and resume without any data loss. Another scenario is if you want to interact with some service and that service is not available, this pattern will help you in reattempting the operation once service is up again.

Since it adds the complexity to the system, it is recommended to use this pattern in the big system where reliability is important.

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

 



ASP.NET Core 2.2.1 Hosting - HostForLIFE.eu :: Quick Micro Services Development Using MicroService4Net (No Containers)

clock July 23, 2018 08:57 by author Peter
I won't be discussing Microservices here because I specifically need to focus on the subject of interest and that shouldn't be diluted. So, the focus area is developing Microservices without the usual containers, like docker etc., but  rather using the existing tools and technologies that belong to ASP.NET. We are targeting the below characteristics of Microservices in this article.

  1. Collection of loosely coupled services
  2. Services with isolated context and so can freely deploy.

Now, let us get an idea of the below terminologies. 

Open Web Interface for .NET
It's a middleware technology, http://owin.org/, and widely using in ASP.NET MVC Web API to enable self-hosting. You need an idea of OWIN before proceeding here.
 
MicroService4Net
It's a wrapper made on top of OWIN to make Microservice development more easy. You are able to create self hosting loosely coupled services without even the need of web servers like IIS. 
 
Two sample projects I uploaded here do simple mathematics of Addition and Multiplication. Here, I have created 2 separate services for each of these operations and you can call them independently. I also made them self hosting without even need of a web server.
 
You may be interested in the below-mentioned code.
 
Run Services using MicroService4Net
  1. var microService = new MicroService(<<port>>);  
  2. microService.Run(args); 
It's self explanatory how to create an instance of MicroService by passing an available port. Then, call microService.Run(args);. Now your service is running. It's that simple! Any MVC controllers defined in your service project can be accessed. Below are my 2 services created for Add and Multiply, they are running on different ports and also in their own context rather than sharing a common context of IIS etc. Here, a console application is basically doing the hosting using OWIN technology. 

As you can see here, hosting has been inside console applications, you can later register it as a Windows Service though. I will  be able to access my both services through browsers. See below.

So now, we have loosely coupled services running without any web server dependency. The technology is OWIN and the tool MicroService4Net made it easy to crack the Microservice part of it. I uploaded 2 projects, and each belongs to these 2 services. You can refer to it and then try to resolve one use case I mentioned below.
 
Use Case to Resolve
A Microservice deployment may contain 100s or 1000s or even more small services and each has its own boundary scope. In a practical scenario, no one wants to run all services 24/7. But what people do, whenever an API of a service has been called, then that service will go up and after execution service will go off again. So services run on demand and as our host is a console application, it seems easy. There are many ways to solve this scenario.

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



ASP.NET Core 2.2.1 Hosting - HostForLIFE.eu :: How to Cancel Long Running Task Using Cancellation Token Source In ASP.NET Core?

clock July 18, 2018 09:09 by author Peter

In this article, we are going to learn how to cancel or interrupt the Long Running Task using the Cancellationtokensource method in ASP.NET Core. So, here is the task: My web application will send POST request by making web service API call and get the data via a third-party library. For example, consider, the application is going to send details about the students through the API and will get the response once the POST data is successfully received and saved on another side. Consider that the application is going to send 5000 bits of data through the API. So, by simply using for-each loop by calling third-party API, we can POST 5000 data.

It will take too long to finish this job. Until this job is done the application will not allow other operations to perform as the job is running in the main thread. To make it possible, we will move to “TASK”, to run this job in a separate thread so that the application can do other operations. To understand this, have a look at the code below.
Var task=Task.Factory.StartNew(()=> CallWebServiceandGetResponceData()); 

The code is creating the task which is making API webservice call inside CallWebServiceandGetResponceData function to send a request and get the response data. So by doing this, the application allows this task operation in a separate thread and we can do other operations in the main thread, which will not affect the task operation. Everything is going fine.

If you are using .NET 4.5 Framework you can use Async and wait for keywords to do this. But in .NET 4.0 we can’t use async and await keywords, so I'm going to use “TASK” to achieve this operation. So, now I need to cancel or stop the task whenever I need to. For example, 2673rd data is currently running inside the CallWebServiceandGetResponceData function, when I hit the stop button I need to cancel or stop calling third-party API and exit the loop. To do this I'm going to use CancellationToken.

.NET 4.0 introduces a lightweight struct called the cancellationToken that provide a mechanism to cancel synchronous and asynchronous operations. CancellationToken consist is a CancellationRequested method, it is a Boolean property that can be polled by code to find out if it has been canceled or the cancellation has been requested.

By using instance of CancellationTokenSource class to get a cancellation token, in cancellation model the cancellation token can be passed freely to the listeners, so that canceling token is cleanly separted from the ability to consume a request for cancellation. Here is the sample code to cancel a task,
CancellationTokenSource mCancellationTokenSource = new CancellationTokenSource(); 
CancellationToken token = mCancellationTokenSource.Token; 
Task < string > ObjTask = Task.Factory.StartNew(() => { 
    while (!token.IsCancellationRequested) { 
        try { 
            For(i = 0; i < totalrecordscount; i++) { 
                If(i == 2341) { 
                    Token.Cancecl(); 
                } 
                // Sending data to other end by api call 
            } 
        } catch () { 
            return; 
        } 
    } 
    return; 
}, token); 


The above code will run continuously in while loop until it gets the cancel request. Once the token gets a cancellation request the control will terminate the entire Task and the control will get back to the main thread. Here, the cancel request is made inside the task based on the condition.

Instead we can also stop the task whenever we want, like after the task started execution, when I hit the stop button from front end the token get cancellation request and terminate the execution. Here, is the sample code to cancel a task by clicking stop button:
Bool istasktostop = false; // declare one global bool variable 
CancellationTokenSource mCancellationTokenSource = new CancellationTokenSource(); 
CancellationToken token = mCancellationTokenSource.Token; 
Task < string > ObjTask = Task.Factory.StartNew(() => { 
    while (!token.IsCancellationRequested) { 
        try { 
            For(i = 0; i < totalrecordscount; i++) { 
                //for each loop its checking weather “istasktostop” is 
                If(istasktostop) { 
                    Token.Cancecl(); 
                } 
                // Sending data to other end by api call 
            } 
        } catch () { 
            return; 
        } 
    } 
    return; 
}, token); 
protected void Stop_Sending_Click(object sender, ImageClickEventArgs e) { 
    istasktostop = true; 
}


Normally, if we did the same operation without task and a cancellationtoken, we can't send stop request when the process is in running mode because the current process occupies  the main thread and we can't interrupt the main thread while it's running. When we did the same process inside the task, it is separated and run at a separate thread, so we can do other processes in the main thread.

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



ASP.NET Core 2.2.1 Hosting - HostForLIFE.eu :: Appsettings.json In ASP.NET Core 2.0

clock July 16, 2018 11:41 by author Peter

As most of you are aware, in ASP.NET Core, we don't have anything called Web.config which we use to write our connection strings or application specific settings. Rather, here we have a file named appsettings.json to store similar information. There are a few very common use cases where we need to maintain multiple appsettings.json files in a single solution. For example,

Multiple application settings per application
When we need to maintain different-different application-specific settings based on the application environment. Say, one can have one type of application settings for Development, another type of application settings for Production, another one for Staging, and so on. Needless to mention, all the appsettings files will have different names.

To implement inheritance

If there are some common settings between multiple application settings file, the developer can come up with a base application settings file and on top of that specific file can be created. In that case, common information need not to be repeated in all the files.

If you are aware of the ASP.NET Core architecture, then you must agree on the point that such scenarios can also be handled very easily in the ASP.Net Core as plugging in multiple sources is very straightforward.

So, coming to the point. My article is all about how to inherit or read data from an appsettings.json file which is outside of my project. This scenario usually comes into the picture when we are maintaining different projects for holding all the shared resources that have to be consumed across many projects in a given solution file. So, in the real world, one project can have its project specific settings as well as some common (or say global) settings which are placed outside its boundary.

Let me first tell you something about my project structure. Here goes my solution structure:

As you can see in the above figure, 'CommonSettings.json' is the file which is kept outside of the main project named 'AllAboutConfigurations' and here is how my both the JSON files look like.

appsettings.json

"Logging": { 
            "IncludeScopes": false, 
            "LogLevel": { "Default": "Warning" } 
         }, 

"MySettings": {  
              "PersonalizedSettings": " It's just for me"
            }  


CommonSettings.json


"MySettings": {  
                     "CommonSettings": "Hi, I'm common setting. Anyone can use me."
            } 


Now, in order to read 'CommonSettings.json' in 'AllAboutConfigurations' project, I have to update the application configuration while constructing the web host as shown below.
public static IWebHost BuildWebHost(string[] args) => 
        WebHost.CreateDefaultBuilder(args) 
            .ConfigureAppConfiguration((webHostBuilderContext, configurationbuilder) => 
            { 
                var environment = webHostBuilderContext.HostingEnvironment; 
                string pathOfCommonSettingsFile = Path.Combine(environment.ContentRootPath,"..","Common"); 
                configurationbuilder 
                        .AddJsonFile("appSettings.json", optional: true) 
                        .AddJsonFile(Path.Combine(pathOfCommonSettingsFile, "CommonSettings.json"), optional: true); 

                configurationbuilder.AddEnvironmentVariables(); 
            }) 
            .UseStartup() 
            .Build(); 


Now, if we want to see something on our web page, we have to update UI code too. Let's make it simple with just a few lines of code as shown below.
@using Microsoft.Extensions.Configuration; 
@inject IConfiguration configuration; 

@{ 
Layout = null; 


<html> 
<head> 
<title>Settings</title> 
</head> 
<body> 
    Personalized Settings: @configuration.GetSection("MySettings")["PersonalizedSettings"]<br />  
    Common Settings: @configuration.GetSection("MySettings")["CommonSettings"]<br /> 
</body> 
</html> 


If you will run your application now, you will be able to see that both the settings are considered as part of a single project.



ASP.NET Core 2.2.1 Hosting - HostForLIFE.eu :: Indexing In-Memory Collections For Blazing Fast Access

clock July 11, 2018 09:26 by author Peter

The CodexMicroORM open source project on GitHub hosts a few useful .NET goodies that can help you write concise code with great performance. In this article, I’ll cover a collection type that supports multi-property indexing and as such, performs very well with equality lookups. It’s common (and relatively easy) to index large lists using a “side dictionary” to improve performance. Let’s consider this example where we start with a business entity that looks like this:
    class Person { 
        public string Name { 
            get; 
            set; 
        } 
        public int ? Age { 
            get; 
            set; 
        } 
    } 


and use a test harness like this,
    List < Person > people = new List < Person > (); 
    for (int i = 1; i <= 20000; ++i) { 
        people.Add(new Person() { 
            Name = $ "P{i}", Age = (i % 70) + 10 
        }); 
    } 
    Stopwatch sw = new Stopwatch(); 
    sw.Start(); 
    int found = 0; 
    for (int i = 1; i <= 1000; ++i) { 
        found += (from p in people where p.Age == 50 select p).Count(); 
    } 
    sw.Stop(); 
    Console.WriteLine($ "{sw.Elapsed.TotalMilliseconds} microseconds per iteration"); 

On my machine, this takes about 627 microseconds per pass of the final loop which is counting people aged “50” out of a basic list we populated with 20,000 Person instances. The iterating is using a simple LINQ to Objects expression, which is fast – but we can do better! Let’s make a change by adding an additional layer – a pass over the data to create an in-memory index using a Dictionary. That changes our final query considerably: finding those aged 50 becomes as simple as accessing the dictionary by key,
    Stopwatch sw = new Stopwatch(); 
    sw.Start(); 
    Dictionary < int ? , ICollection < Person >> ageMap = new Dictionary < int ? , ICollection < Person >> (); 
    foreach(var p in people) { 
        var age = p.Age; 
        if (ageMap.ContainsKey(age)) { 
            ageMap[age].Add(p); 
        } else { 
            var list = new List < Person > (); 
            list.Add(p); 
            ageMap[age] = list; 
        } 
    } 
    int found = 0; 
    for (int i = 1; i <= 1000; ++i) { 
        found += ageMap[50].Count(); 
    } 
    sw.Stop(); 
    Console.WriteLine($ "{sw.Elapsed.TotalMilliseconds} microseconds per iteration"); 


Even including the time spent building this dictionary, this runs at 9.8 microseconds per iteration. That’s 64 times faster than our LINQ query! (It’s even more dramatic if we used “int” instead of “int?” – then it’s 368 times faster!) This is probably not a great surprise: dictionaries excel with reads. A question could be: why bother with the list at all? For my purposes here, I’m assuming you may not have control over the collection type: for example, you might be consuming it from an existing object model (such as one you might be getting out of Entity Framework), or you might have an object that could be indexed in multiple ways and a more generalized collection makes sense.

The natural temptation might be to use indexes like this for any property where you might query like we did for “Age.” Too bad it increased our code size in the above example; there’s an easy solution for that, though.
ConcurrentIndexedList<T>

To streamline the use of indexes, the ConcurrentIndexedList<T> class comes to the rescue. First, let’s add a NuGet reference to CodexMicroORM.Core,

ConcurrentIndexedList
Now our above example can be simplified greatly,
    ConcurrentIndexedList < Person > people = new ConcurrentIndexedList < Person > (nameof(Person.Age), nameof(Person.Name)); 
    for (int i = 1; i <= 20000; ++i) { 
        people.Add(new Person() { 
            Name = $ "P{i}", Age = (i % 70) + 10 
        }); 
    } 
    Stopwatch sw = new Stopwatch(); 
    sw.Start(); 
    int found = 0; 
    for (int i = 1; i <= 1000; ++i) { 
        found += people.GetAllByNameNoLock(nameof(Person.Age), 50).Count(); 
    } 
    sw.Stop(); 
    Console.WriteLine($ "{sw.Elapsed.TotalMilliseconds} microseconds per iteration"); 


In this case, we’ve indexed both Age and Name, as specified in the constructor. Because of that, we could do something like this,
found += people.GetAllByNameNoLock(nameof(Person.Age), 50).Union(people.GetAllByNameNoLock(nameof(Person.Name), "P15")).Count(); 

Notice here we’re leveraging LINQ to Objects where we’re looking for the union of results from two types of indexed queries: one by age, one by name. The performance on the age lookup isn’t quite as crazy as with a single raw dictionary, but it’s still 40 times better than the plain LINQ query.

We can even index null values, too, which is something that would have complicated our original hand-rolled index for something like Name which is a reference type. For example, this works as expected, if we supported null Names:
    found += people.GetAllByNameNoLock(nameof(Person.Name), null).Count(); 

There’s one big caveat here: the current implementation of ConcurrentIndexedList<T> requires that your “T” in this case implement the ICEFIndexedListItem interface. I do this for a couple of reasons,

To avoid reflection. It does introduce boxing which does kill some performance, but not as much as would happen if we resorted to using System.Reflection.
Offers some value-add such as the ability to “unwrap” values from your objects. In the case of the framework itself, I want to index objects that are contained inside another object, namely a WeakReference object’s “Target” property. If I didn’t do this, I’d be indexing the WeakReference itself which isn’t useful to me.

The code change I used here to let my Person class work includes,
    class Person: ICEFIndexedListItem { 
        public string Name { 
            get; 
            set; 
        } 
        public int ? Age { 
            get; 
            set; 
        } 
        public object GetValue(string propName, bool unwrap) { 
            switch (propName) { 
                case nameof(Person.Name): 
                    return Name; 
                case nameof(Person.Age): 
                    return Age; 
            } 
            throw new ArgumentException("propName is not a valid property."); 
        } 
    }

If you’re unable to modify your business objects, a version of this could be constructed that does use reflection. I plan a second article to discuss my “optimized reflection helpers,” also available for free within the framework.

Added Benefits
Most operations on the collection are guarded by reader/writer locks, meaning multiple concurrent readers are allowed, but only one writer at a time can modify the collection. This resembles the behavior of the types in System.Collections.Concurrent – which I actually used more extensively in the 0.2 version of the framework, but have migrated away for potentially large/unbounded collections based on observed memory and performance issues. In this case, the simplicity of basic dictionaries and slim reader/writer locks seems to do well. Thread-safety may not be useful in every case – but it opens the door to injecting further performance improvements in your apps through the use of the Parallel .NET framework class.

In the 0.5 release of the library, I’ve included the ability to set an initial capacity for the collection. As is true with any dictionary, it’s a good idea to set this if you know up-front the approximate maximum size expected for the collection. Setting it can avoid the resize operations which the collection would otherwise have to do when it hits a size limit (as it grows). If your collections are very large, resize operations can become very slow and memory intensive.

It’s true that LINQ to Objects is often “fast enough” for reasonably small data sets. ConcurrentIndexedList<T> is a general-purpose class to support cases where you either anticipate the possibility for a large data set or can’t anticipate the amount of data at all and want to “play it safe” based on known index requirements. Other libraries exist that try to address the same problem. For example, i4o offers a way to “wrap” collections in a way that lets you use ordinary LINQ to Objects and have that in turn use indexes over the underlying data. This is a great concept, but in real-world benchmarks, I’ve seen it not always deliver in a truly generic way. (Some cases work well, some do not - and can perform worse.) There are different reasons for this, and it’s relevant to work I’m doing in CodexMicroORM, so will be likely covering deeper details in future articles.



ASP.NET Core 2.2.1 Hosting - HostForLIFE.eu :: Push Notification Using Firebase Cloud Messaging Using .NET

clock July 9, 2018 11:52 by author Peter

Firebase Cloud Messaging (FCM) is a cross-platform messaging solution that lets you reliably deliver messages at no cost.
Steps to get server key / SenderID

  1. To get the keys, log in to Firebase account.
  2. Select the project from the list.
  3. Click on "Setting" gear icon and click "Project Settings". 

  4. Click on "Cloud Messaging" tab to select "Server key" and "Sender key" from the below screen.

Add the below code to send push notifications.

//Create the web request with fire base API
WebRequest tRequest = WebRequest.Create("https://fcm.googleapis.com/fcm/send");  
tRequest.Method = "post";  
//serverKey - Key from Firebase cloud messaging server  
tRequest.Headers.Add(string.Format("Authorization: key={0}", serverKey));  
//Sender Id - From firebase project setting  
tRequest.Headers.Add(string.Format("Sender: id={0}", senderId));  
tRequest.ContentType = "application/json";  
var payload = new {  
    to = deviceId,  
        priority = "high",  
        content_available = true,  
        notification = new {  
            body = txtmsg,  
                title = txttitle.Replace(":", ""),  
                sound = "sound.caf",  
                badge = badgeCounter  
        },  
};  
var serializer = new JavaScriptSerializer();  
Byte[] byteArray = Encoding.UTF8.GetBytes(payload);  
tRequest.ContentLength = byteArray.Length;  
using(Stream dataStream = tRequest.GetRequestStream()) {  
    dataStream.Write(byteArray, 0, byteArray.Length);  
    using(WebResponse tResponse = tRequest.GetResponse()) {  
        using(Stream dataStreamResponse = tResponse.GetResponseStream()) {  
            if (dataStreamResponse != null) using(StreamReader tReader = new StreamReader(ataStreamResponse)) {  
                String sResponseFromServer = tReader.ReadToEnd();  
                result.Response = sResponseFromServer;  
            }  
        }  
    }  
}

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



ASP.NET Core 1.1 Hosting - HostForLIFE.eu :: How to Create Login Form In ASP.NET?

clock March 9, 2017 07:58 by author Peter

In this tutorial, I will show you how to create login form in ASP.NET core. You can easily implement this concept anywhere in .NET applications. I have used some controls to build the login form in a .NET application.

  •  Text Box
  •  Label and Button

Please follow these steps to make this application.
Step 1
First, open your Visual Studio -> File -> New -> Website -> ASP.NET Empty website and click OK. Now, open Solution Explorer and go to Add New Item -> Web form -> click Add.

Step 2
Now, make a Login page like the one given below.
.aspx or design page (front-end)
    <html xmlns="http://www.w3.org/1999/xhtml">  
      
    <head runat="server">  
        <title>Login Form</title>  
    </head>  
      
    <body>  
        <form id="form1" runat="server">  
            <div>  
                <table>  
                    <tr>  
                        <td> Username: </td>  
                        <td>  
                            <asp:TextBox ID="txtUserName" runat="server" />  
                            <asp:RequiredFieldValidator ID="rfvUser" ErrorMessage="Please enter Username" ControlToValidate="txtUserName" runat="server" /> </td>  
                    </tr>  
                    <tr>  
                        <td> Password: </td>  
                        <td>  
                            <asp:TextBox ID="txtPWD" runat="server" TextMode="Password" />  
                            <asp:RequiredFieldValidator ID="rfvPWD" runat="server" ControlToValidate="txtPWD" ErrorMessage="Please enter Password" /> </td>  
                    </tr>  
                    <tr>  
                        <td> </td>  
                        <td>  
                            <asp:Button ID="btnSubmit" runat="server" Text="Submit" /> </td>  
                    </tr>  
                </table>  
            </div>  
        </form>  
    </body>  
      
    </html>  


Now, create an event for click button, such as -  onclick="<>".
    onclick="btnSubmit_Click"  

So, our button tag will be like <asp:Button ID="btnSubmit" runat="server" Text="Submit" onclick="btnSubmit_Click" />. And in login.aspx.cs page, we need to write the following code.

C# Code --Code behind(Aspx.cs)
    using System;  
    using System.Data;  
    using System.Data.SqlClient;  
    using System.Configuration;  


After adding the namespaces, write the following code in code behind.
    protected void btnSubmit_Click(object sender, EventArgs e) {  
        SqlConnection con = newSqlConnection(ConfigurationManager.ConnectionStrings["dbconnection"].ConnectionString);  
        con.Open();  
        SqlCommand cmd = new SqlCommand("select * from UserInformation where UserName =@username and Password=@password", con);  
        cmd.Parameters.AddWithValue("@username", txtUserName.Text);  
        cmd.Parameters.AddWithValue("@password", txtPWD.Text);  
        SqlDataAdapter da = new SqlDataAdapter(cmd);  
        DataTable dt = new DataTable();  
        da.Fill(dt);  
        if (dt.Rows.Count > 0) {  
            Response.Redirect("Details.aspx");  
        } else {  
            ClientScript.RegisterStartupScript(Page.GetType(), "validation", "<script language='javascript'>alert('Invalid Username and Password')</script>");  
        }  
    }  


Now, for connecting it with the database, write the database connection string like the following.

Web Config
    <connectionStrings>  
        <add name="dbconnection" connectionString="Data Source=BrajeshKr;Integrated Security=true;Initial Catalog=MyDB" /> </connectionStrings>

That's it. Now, our Login page is ready to be executed. You can download the code for this application and run that on your Visual Studio.

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