European ASP.NET 4.5 Hosting BLOG

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

European ASP.NET Core Hosting - HostForLIFE.eu :: Using Sorted Sets Of Redis To Delay Execution In ASP.NET Core

clock April 14, 2020 07:33 by author Peter

In a previous article, I showed you how to delay execution via keyspace notifications of Redis in ASP.NET Core, and I will introduce another solution based on Redis.
Sorted Sets, a data structure of Redis, also can help us work it out.

We can make a timestamp as score, and the data as value. Sorted Sets provides a command that can return all the elements in the sorted set  with a score between two special scores. Setting 0 as the minimum score and current timestamp as the maximum score, we can get all the values whose timestamp are less than the current timestamp, and they should be executed at once and should be removed from Redis.
 
Taking a sample for more information.
 
Add some values at first.

ZADD task:delay 1583546835 "180" 
ZADD task:delay 1583546864 "181" 
ZADD task:delay 1583546924 "182"  

Suppose the current timestamp is 1583546860, so we can get all values via the following command.

ZRANGEBYSCORE task:delay 0 1583546860 WITHSCORES LIMIT 0 1

We will get the value 180 from the above sample, and then we can do what we want to do.

Now, let's take a look at how to do this in ASP.NET Core.

Create Project
Create a new ASP.NET Core Web API project and install CSRedisCore.
    <ItemGroup> 
        <PackageReference Include="CSRedisCore" Version="3.4.1" /> 
    </ItemGroup> 


Add an interface named ITaskServices and a class named TaskServices.
    public interface ITaskServices 
    { 
        Task DoTaskAsync(); 
     
        Task SubscribeToDo(); 
    } 
     
    public class TaskServices : ITaskServices 
    {        
        public async Task DoTaskAsync() 
        { 
            // do something here 
            // ... 
     
            // this operation should be done after some min or sec 
     
            var cacheKey = "task:delay"; 
            int sec = new Random().Next(1, 5); 
            var time = DateTimeOffset.Now.AddSeconds(sec).ToUnixTimeSeconds(); 
            var taskId = new Random().Next(1, 10000); 
            await RedisHelper.ZAddAsync(cacheKey, (time, taskId)); 
            Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} done {taskId} here - {sec}"); 
        } 
     
        public async Task SubscribeToDo() 
        { 
            var cacheKey = "task:delay"; 
            while (true) 
            { 
                var vals = RedisHelper.ZRangeByScore(cacheKey, -1, DateTimeOffset.Now.ToUnixTimeSeconds(), 1, 0); 
     
                if (vals != null && vals.Length > 0) 
                { 
                    var val = vals[0]; 
     
                    // add a lock here may be more better 
                    var rmCount = RedisHelper.ZRem(cacheKey, vals); 
     
                    if (rmCount > 0) 
                    { 
                        Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} begin to do task {val}"); 
                    } 
                } 
                else 
                { 
                    await Task.Delay(500); 
                } 
            } 
        } 
    } 


Here we will use DateTimeOffset.Now.AddSeconds(sec).ToUnixTimeSeconds() to generate the timestamp, the sec parameter means that we should execute the task after some seconds. For the delay execution, it will poll the values from Redis to consume the tasks, and make it sleep 500 milliseconds if cannot get some values.

When we get a value from Redis, before we execute the delay task, we should remove it from Redis at first.

Here is the entry of this operation.

    [ApiController] 
    [Route("api/tasks")] 
    public class TaskController : ControllerBase 
    { 
        private readonly ITaskServices _svc; 
     
        public TaskController(ITaskServices svc) 
        { 
            _svc = svc; 
        } 
     
        [HttpGet] 
        public async Task<string> Get() 
        { 
            await _svc.DoTaskAsync(); 
            return "done"; 
        } 
    } 


We will put the subscribe to a BackgroundService

    public class SubscribeTaskBgTask : BackgroundService 
    { 
        private readonly ILogger _logger; 
        private readonly ITaskServices _taskServices; 
     
        public SubscribeTaskBgTask(ILoggerFactory loggerFactory, ITaskServices taskServices) 
        { 
            this._logger = loggerFactory.CreateLogger<RefreshCachingBgTask>(); 
            this._taskServices = taskServices; 
        } 
     
        protected override async Task ExecuteAsync(CancellationToken stoppingToken) 
        { 
            stoppingToken.ThrowIfCancellationRequested(); 
            await _taskServices.SubscribeToDo(); 
        } 
    } 


At last, we should register the above services in startup class.
    public class Startup 
    { 
        // ... 
         
        public void ConfigureServices(IServiceCollection services) 
        { 
            var csredis = new CSRedis.CSRedisClient("127.0.0.1:6379"); 
            RedisHelper.Initialization(csredis); 
     
            services.AddSingleton<ITaskServices, TaskServices>(); 
            services.AddHostedService<SubscribeTaskBgTask>(); 
     
            services.AddControllers(); 
        } 
    } 

Here is the result after running this application.



European ASP.NET Core Hosting - HostForLIFE.eu :: Object reference not set to an instance of object

clock April 7, 2020 09:01 by author Peter

Error "object reference not set to an instance of an object"
This is one of the most common errors when developing an application. In this article, I will be presenting five of the most common mistakes that result with this error and will explain how to avoid them.

Why does this error happen?
This error's description speaks for itself but when you do not have much experience in development, it is very difficult to understand. So, this error description says that an object that is being called to get or set its value has no reference. This means that you are trying to access an object that was not instantiated.

Why should I know this?
This is important in order to avoid runtime errors that could possibly expose your sensitive data and this could lead to a vulnerability breach. Vulnerability breaches are usually used by hackers for a cyber attack to steal your data or to take your server offline.

How to avoid exposing code and entities?
You must always wrap code that could possibly throw an exception inside try-catch blocks. There are others security approaches that you can use to protect your data that can be found here.

Common mistakes
Objects used in this sample.

Controller
public class HomeController : Controller 
   { 
       SampleObj sampleObj; 
       SampleChildObj sampleChild; 
       List<string> lstSample; 
       public IActionResult Index() 
       { 
           return View(); 
       } 
 
       public IActionResult About() 
       { 
           ViewData["Message"] = "Your application description page."; 
 
           return View(); 
       } 
 
       public IActionResult Contact() 
       { 
           ViewData["Message"] = "Your contact page."; 
 
           return View(); 
       } 
 
       public IActionResult Error() 
       { 
           return View(); 
       } 
       public IActionResult NewObject() 
       { 
           sampleChild.Item2 = "error"; 
           return View(); 
       } 
 
       public IActionResult ConditionStatement() 
       { 
           if (true == false) 
           { 
               sampleChild = new SampleChildObj(); 
               sampleChild.Item2 = ""; 
           } 
           else 
               sampleChild.Item2 = "error"; 
 
           return View(); 
       } 
       public IActionResult ObjectInsideObject() 
       { 
           sampleObj = new SampleObj(); 
           sampleObj.ChildObj.Item2 = "error"; 
           return View(); 
       } 
       public IActionResult AddInNullList() 
       { 
           lstSample.Add("error"); 
           return View(); 
       } 
   } 

Classes
public class SampleObj 

 
    public string Item1 { get; set; } 
    public SampleChildObj ChildObj { get; set; } 

public class SampleChildObj  

    public string Item2 { get; set; } 


New object not instantiated
Practical example:
Here, we have a sample situation of when we have this error.

public IActionResult NewObject() 

    sampleChild.Item2 = "error"; 
    return View(); 


This happens when you create a new object but do not instantiate it before getting/setting a value.
Condition statement(if, switch)

Practical example:
Here, we have a sample situation of when we have this error,

public IActionResult ConditionStatement() 

    if (true == false) 
    { 
        sampleChild = new SampleChildObj(); 
        sampleChild.Item2 = ""; 
    } 
    else 
        sampleChild.Item2 = "error"; 
 
    return View(); 


Why does this happen?
This is a very common mistake. It happens when you create an object that is going to be instantiated inside a conditional statement but forgets to instantiate it in one of the conditions and try to read/write on it.

Object Inside Object

Practical Example
Here, we have a sample situation of when we have this error:

public IActionResult ObjectInsideObject() 

    sampleObj = new SampleObj(); 
    sampleObj.ChildObj.Item2 = "error"; 
    return View(); 


Why this happens?
It happens when you have an object with many child objects. So, you instantiate the main object but forget to instantiate its child before trying to get/set its value.

Add item in a null list

Practical Example
Here we have a sample situation of when we have this error,
public IActionResult AddInNullList() 

    lstSample.Add("error"); 
    return View(); 
}


Why does this happen?
When you are trying to read/write data in a list that was not instantiated before.

Important
In order to avoid exposing your data, you must always handle exceptions. Read more about how to do that here.
The items listed above are some of the most common ways to throw this type of error but there are many other situations in which we may face it. Always remember to check if your objects are instantiated before reading or writing data into them.

Best practices
Tips about commenting your code, making it more readable in order to help others developers to understand it.
Object naming practices, creating a pattern to name variables, services, methods.
Handling errors to not show sensitive data to your users.
Security tricks to protect your data.
Reading/writing data without breaking your architecture.

*I am planning to write more about common mistakes and to share tips to improve code quality. If you have any specific topic that you would like to read here, please write it below in the comments section.



European ASP.NET Core Hosting - HostForLIFE.eu :: Read and Write a CSV File in ASP.NET Core

clock March 31, 2020 11:06 by author Peter
For this blog, my agenda is to provide a step-by-step solution to read and write CSV files in ASP.NET Core 3.0, and CSVHelper. The Same Logic will work for Web Application, Windows Application, and Console Application. In this post, I'm going to create a sample Console Application to show you the process.

Steps:
  1. Create a Console Application project
  2. Create a student class inside the project
  3. Install the CSVHelper from NuGet Package Manager
  4. Add Mappers folder and inside add a mapper Class for Student
  5. Add Services Folder in the project and Add StudentService Class inside it
  6. Write the Logic inside the main method of Program file as its starting point of the application
Create a Console Application project
Give the Name to The Project as "ReadWriteCSVFile". You can give any name.
 
Create a student class inside the project 
Write the below code inside the Student class:

namespace ReadWriteCSVFile {  
    public class Student {  
        public int RollNo {  
            get;  
            set;  
        }  
        public string Name {  
            get;  
            set;  
        }  
        public string Course {  
            get;  
            set;  
        }  
        public decimal Fees {  
            get;  
            set;  
        }  
        public string Mobile {  
            get;  
            set;  
        }  
        public string City {  
            get;  
            set;  
        }  
    }  

In the next step, we are going to install the CSVHelper package so that it will help us to read and write the CSV file in an easy way.

Now Install the CSVHelper from NuGet Package Manager --Version (12.2.1),

  • Step 1 - Right Click on the Project
  • Step 2 - Go To "Manage NuGet Packages..."
  • Step 3 - Go To Browse Tab then move to the Search area
  • Step 4 - Type "CSVHelper" in the search box

Here you will see a list of packages. Choose the first one and move it to the right-side panel. You will see one option as Version: (If not installed, if you already installed, then you will see both Installed and Version, two options). Select Version 12.2.1 and click on the install button and follow the steps to install successfully.

Add "Mappers" folder and inside it add mapper Class for Student

  • Here you can give any name to the folder and class
  • Give the proper name to the class as "StudentMap"
  • Make this class as sealed

Write the below code inside the StudentMap Class:

namespace ReadWriteCSVFile.Mappers {  
    public sealed class StudentMap: ClassMap < Student > {  
        public StudentMap() {  
            Map(x => x.RollNo).Name("RollNo");  
            Map(x => x.Name).Name("Name");  
            Map(x => x.Course).Name("Course");  
            Map(x => x.Fees).Name("Fees");  
            Map(x => x.Mobile).Name("Mobile");  
            Map(x => x.City).Name("City");  
        }  
    }  

Add "Services" Folder in the project and Add StudentService Class inside it:

  • Here, you can give any name to the folder and class
  • Give the proper name to the class as "StudentService"

Write the below Code inside the StudentService Class

namespace ReadWriteCSVFile.Services {  
    public class StudentService {  
        public List < Student > ReadCSVFile(string location) {  
            try {  
                using(var reader = new StreamReader(location, Encoding.Default))  
                using(var csv = new CsvReader(reader)) {  
                    csv.Configuration.RegisterClassMap < StudentMap > ();  
                    var records = csv.GetRecords < Student > ().ToList();  
                    return records;  
                }  
            } catch (Exception e) {  
                throw new Exception(e.Message);  
            }  
        }  
        public void WriteCSVFile(string path, List < Student > student) {  
            using(StreamWriter sw = new StreamWriter(path, false, new UTF8Encoding(true)))  
            using(CsvWriter cw = new CsvWriter(sw)) {  
                cw.WriteHeader < Student > ();  
                cw.NextRecord();  
                foreach(Student stu in student) {  
                    cw.WriteRecord < Student > (stu);  
                    cw.NextRecord();  
                }  
            }  
        }  
    }  

Write the Logic inside the main method of Program file as its starting point of the application.
Change the code inside the Main method of Program class as shown below:

 

namespace ReadWriteCSVFile {  
    class Program {  
        static void Main(string[] args) {  
            Console.WriteLine("Start CSV File Reading...");  
            var _studentService = new StudentService();  
            var path = @ "D:\Tutorials\Student.csv";  
            //Here We are calling function to read CSV file  
            var resultData = _studentService.ReadCSVFile(path);  
            //Create an object of the Student class  
            Student student = new Student();  
            student.RollNo = 5;  
            student.Name = "Lucy";  
            student.Course = "B.Tech";  
            student.Fees = 75000;  
            student.Mobile = "7788990099";  
            student.City = "Pune";  
            resultData.Add(student);  
            //Here We are calling function to write file  
            _studentService.WriteCSVFile(@ "D:\Tutorials\NewStudentFile.csv", resultData);  
            //Here D: Drive and Tutorials is the Folder name, and CSV File name will be "NewStudentFile.csv"  
            Console.WriteLine("New File Created Successfully.");  
        }  
    }  

 



ASP.NET Core Hosting - HostForLIFE.eu :: Progressive Retry for Network Calls

clock March 18, 2020 11:55 by author Peter

In today's mobile world, many calls across the internet or network could fail for many reasons. Some of the reasons could be the service is busy, the network is slow and many more. For these types of calls, it’s advisable to retry the call if there is an error. The current code base I am working on connects to Salesforce to retrieve and update data. Salesforce is one of those backend services that could experience these types of issues.

To help with these types of network issues, I have added a new method to my open-source code called ProgressiveRetry(). This method will try the call a given number of times. If there is an error, it will wait for a given milliseconds that increases with each error. Below is the code for this call.

    /// <summary> 
    /// Progressive retry for a function call. 
    /// </summary> 
    /// <param name="operation">The operation to perform.</param> 
    /// <param name="retryCount">The retry count (default 3).</param> 
    /// <param name="retryWaitMilliseconds">The retry wait milliseconds (default 100).</param> 
    /// <returns>System.Int32.</returns> 
    public static int ProgressiveRetry(Action operation, byte retryCount = 3,  
                                       int retryWaitMilliseconds = 100) 
    { 
        Encapsulation.TryValidateParam<ArgumentNullException>(operation != null); 
        Encapsulation.TryValidateParam<ArgumentOutOfRangeException>(retryCount > 0); 
        Encapsulation.TryValidateParam<ArgumentOutOfRangeException>(retryWaitMilliseconds > 0); 
      
        var attempts = 0; 
      
        do 
        { 
            try 
            { 
                attempts++; 
     
                 operation(); 
                return attempts; 
     
            } 
            catch (Exception ex) 
            { 
                if (attempts == retryCount) 
                { 
                    throw; 
                } 
      
                Debug.WriteLine(ex.GetAllMessages()); 
      
                Task.Delay(retryWaitMilliseconds * attempts).Wait(); 
                   } 
            } while (true); 
        } 
    } 


Here is example code on how to use ProgressiveRetry().
    var result = false; 
    var count = ExecutionHelper.ProgressiveRetry(() => 
    { 
        result = NetworkHelper.IsHostAvailable("wordpress.com"); 
    } 
    , retryCount: 3, retryWaitMilliseconds: 225); 
    Console.WriteLine($"Host available {result}. Tried call {count} times.");

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.



ASP.NET Core Hosting - HostForLIFE.eu :: Using Redis To Delay Execution In ASP.NET Core

clock March 3, 2020 11:07 by author Peter

Due to some business requirements, many operations should not begin to execute right away;  they should begin after some seconds, minutes or hours. For example, say there is a task, and it contains two steps. When we finish the first step, the second step should begin after 5 minutes.
 

How can we solve this problem?
Thread.Sleep() and Task.Delay() is a very easy solution that we can use. But it may block our applictions.
 
And in this article, I will introduce a solution based on keyspace notifications of Redis.
 
Here we will use expired events to do it, but this solution also has some limitations , because it may have a significant delay. That means that delay of execution may have smoe error, and will not be very accurate!
 
Let's take a look at this solution.
 
Set Up Redis
Keyspace notifications is a feature available since 2.8.0, so the version of Redis should not be less than 2.8.0.
 
We should modify an important configuration so that we can enable this feature.
    ############################# Event notification ############################## 
    
    # Redis can notify Pub/Sub clients about events happening in the key space. 
    # This feature is documented at http://redis.io/topics/notifications 
    # 
    # ......... 
    # 
    #  By default all notifications are disabled because most users don't need 
    #  this feature and the feature has some overhead. Note that if you don't 
    #  specify at least one of K or E, no events will be delivered. 
    notify-keyspace-events "" 


The default value of notify-keyspace-events is empty, we should modify it to Ex.
    notify-keyspace-events "Ex" 

Then we can startup the Redis server.

Create Project
Create a new ASP.NET Core Web API project and install CSRedisCore.
    <Project Sdk="Microsoft.NET.Sdk.Web"> 
     
      <PropertyGroup> 
        <TargetFramework>netcoreapp3.1</TargetFramework> 
      </PropertyGroup> 
     
      <ItemGroup> 
        <PackageReference Include="CSRedisCore" Version="3.4.1" /> 
      </ItemGroup> 
     
    </Project> 

Add an interface named ITaskServices and a class named TaskServices.
    public interface ITaskServices 
    { 
        void SubscribeToDo(string keyPrefix); 
     
        Task DoTaskAsync(); 
    } 
     
    public class TaskServices : ITaskServices 
    { 
        public async Task DoTaskAsync() 
        { 
            // do something here 
            // ... 
     
            // this operation should be done after some min or sec 
            var taskId = new Random().Next(1, 10000); 
            int sec = new Random().Next(1, 5); 
     
            await RedisHelper.SetAsync($"task:{taskId}", "1", sec); 
            await RedisHelper.SetAsync($"other:{taskId + 10000}", "1", sec); 
        } 
     
        public void SubscribeToDo(string keyPrefix) 
        { 
            RedisHelper.Subscribe( 
                ("__keyevent@0__:expired", arg => 
                    { 
                        var msg = arg.Body; 
                        Console.WriteLine($"recive {msg}"); 
                        if (msg.StartsWith(keyPrefix)) 
                        { 
                            // read the task id from expired key 
                            var val = msg.Substring(keyPrefix.Length); 
                            Console.WriteLine($"Redis + Subscribe {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} begin to do task {val}"); 
                        } 
                    }) 
            ); 
        } 
    } 


As you can see, we set a redis key with expiration. The expiration is the delay time.
 
For the delay execution, we can find it in SubscribeToDo method. It subscribes a channel named __keyevent@0__:expired.
 
When a key is expired, redis server will publish a message to this channel, and subscribers will receive it.
 
After reciving the notification, the client will begin to do the job.
 
Before the client receives the notification, the delay job will not be executed, so that it can help us to do the job for a delay.
 
Here is the entry of this operation.
    [ApiController] 
    [Route("api/tasks")] 
    public class TaskController : ControllerBase 
    { 
        private readonly ITaskServices _svc; 
     
        public TaskController(ITaskServices svc) 
        { 
            _svc = svc; 
        } 
     
        [HttpGet] 
        public async Task<string> Get() 
        { 
            await _svc.DoTaskAsync(); 
            System.Console.WriteLine("done here"); 
            return "done"; 
        } 
    } 


Put the subscriber to a BackgroundService, so that it can run in the background.
    public class SubscribeTaskBgTask : BackgroundService 
    { 
        private readonly ILogger _logger; 
        private readonly ITaskServices _taskServices; 
     
        public SubscribeTaskBgTask(ILoggerFactory loggerFactory, ITaskServices taskServices) 
        { 
            this._logger = loggerFactory.CreateLogger<RefreshCachingBgTask>(); 
            this._taskServices = taskServices; 
        } 
     
        protected override Task ExecuteAsync(CancellationToken stoppingToken) 
        { 
            stoppingToken.ThrowIfCancellationRequested(); 
     
            _taskServices.SubscribeToDo("task:"); 
     
            return Task.CompletedTask; 
        } 
    } 


At last, we should register the above services in startup class.
    public class Startup 
    { 
        // ... 
         
        public void ConfigureServices(IServiceCollection services) 
        { 
            var csredis = new CSRedis.CSRedisClient("127.0.0.1:6379"); 
            RedisHelper.Initialization(csredis); 
     
            services.AddSingleton<ITaskServices, TaskServices>(); 
            services.AddHostedService<SubscribeTaskBgTask>(); 
     
            services.AddControllers(); 
        } 
    } 


Here is the result after running this application.

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.



ASP.NET Core Hosting - HostForLIFE.eu :: How to Steps To Generate Excel Using EPPlus?

clock February 25, 2020 08:01 by author Peter

My work is to create an excel file, which will contain 3 fields: Address, Latitude and longitude.The user will upload an Address in an excel file and after reading the addresses from an excel file, I have to retrieve Latitude and longitude, using Bing MAP API and build another excel file, which can contain Addresses beside the Latitude and longitude of that address and download the new excel file to the user's end.

Create a MVC Application and add EPPLUS from NuGet package manager to your solution.

Now, Add the code to your .cshtml page.

<h2>Upload File</h2> 
 
sing (Html.BeginForm("Upload", "Home", null, FormMethod.Post, new { enctype = "multipart/form-data" })) 
  { 
      @Html.AntiForgeryToken() 
      @Html.ValidationSummary() 
 
      <div class="form-group"> 
          <input type="file" id="dataFile" name="upload" /> 
      </div> 
 
      <div class="form-group"> 
          <input type="submit" value="Upload" class="btn btn-default" /> 
      </div> 
 
       
  } 


And then, add the code, mentioned below to your controller.

[HttpPost] 
        public ActionResult Upload(HttpPostedFileBase upload) 
        { 
            if (ModelState.IsValid) 
            { 
                if (Path.GetExtension(upload.FileName) == ".xlsx") 
                { 
                    ExcelPackage package = new ExcelPackage(upload.InputStream); 
            //From This part we will read excel file 
                    DataTable dt = ExcelPackageExtensions.ToDataTable(package); 
 
 
                    DataTable dtExcel = new DataTable(); 
                    dtExcel.Columns.Add("Address", typeof(String)); 
                    dtExcel.Columns.Add("LAT", typeof(Double)); 
                    dtExcel.Columns.Add("LONG", typeof(Double)); 
 
                    List<Coordinates> lstCor = new List<Coordinates>(); 
                    for (int i = 0; i < dt.Rows.Count; i++) 
                    { 
                        //Fill the new data Table to generate new excel file 
                    } 
            //This method will generate new excel and download the same 
                    generateExcel(dtExcel);                  
                } 
            } 
            return View(); 
        } 


“ExcelPackageExtensions.ToDataTable(package)” for this create a new class with the name ExcelPackageExtensions and create a static method with the name “ToDataTable()”. The code is mentioned below.

public static class ExcelPackageExtensions 
    { 
        public static DataTable ToDataTable(this ExcelPackage package) 
        { 
            ExcelWorksheet workSheet = package.Workbook.Worksheets.First(); 
            DataTable table = new DataTable(); 
            foreach (var firstRowCell in workSheet.Cells[1, 1, 1, workSheet.Dimension.End.Column]) 
            { 
                table.Columns.Add(firstRowCell.Text); 
            } 
 
            for (var rowNumber = 2; rowNumber <= workSheet.Dimension.End.Row; rowNumber++) 
            { 
                var row = workSheet.Cells[rowNumber, 1, rowNumber, workSheet.Dimension.End.Column]; 
                var newRow = table.NewRow(); 
                foreach (var cell in row) 
                { 
                    newRow[cell.Start.Column - 1] = cell.Text; 
                } 
                table.Rows.Add(newRow); 
            } 
            return table; 
        } 
    } 

Now, add the code part to generate and download an Excel file.
[NonAction] 
        public void generateExcel(DataTable Dtvalue) 
        { 
            string excelpath = ""; 
            excelpath = @"C:\Excels\abc.xlsx";//Server.MapPath("~/UploadExcel/" + DateTime.UtcNow.Date.ToString() + ".xlsx"); 
            FileInfo finame = new FileInfo(excelpath); 
            if (System.IO.File.Exists(excelpath)) 
            { 
                System.IO.File.Delete(excelpath); 
            } 
            if (!System.IO.File.Exists(excelpath)) 
            { 
                ExcelPackage excel = new ExcelPackage(finame); 
                var sheetcreate = excel.Workbook.Worksheets.Add(DateTime.UtcNow.Date.ToString()); 
                if (Dtvalue.Rows.Count > 0) 
                { 
                    for (int i = 0; i < Dtvalue.Rows.Count; ) 
                    { 
                        sheetcreate.Cells[i + 1, 1].Value = Dtvalue.Rows[i][0].ToString(); 
                        sheetcreate.Cells[i + 1, 2].Value = Dtvalue.Rows[i][1].ToString(); 
                        sheetcreate.Cells[i + 1, 3].Value = Dtvalue.Rows[i][2].ToString(); 
                        i++; 
                    } 
                } 
                //sheetcreate.Cells[1, 1, 1, 25].Style.Font.Bold = true; 
                //excel.Save(); 
 
                var workSheet = excel.Workbook.Worksheets.Add("Sheet1"); 
                //workSheet.Cells[1, 1].LoadFromCollection(data, true); 
                using (var memoryStream = new MemoryStream()) 
                { 
                    Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; 
                    Response.AddHeader("content-disposition", "attachment;  filename=Contact.xlsx"); 
                    excel.SaveAs(memoryStream); 
                    memoryStream.WriteTo(Response.OutputStream); 
                    Response.Flush(); 
                    Response.End(); 
                } 
            } 
 
        } 

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 :: Add Custom Parameters In Swagger Using ASP.NET Core 3.1

clock February 18, 2020 10:54 by author Peter

Web APIs have some common parameters in a project, mabybe those paramters should be passed via header or query, etc.For example, there is a Web API url, https://yourdomain.com/api/values, and when we access this Web API, we should add timestamp, nonce and sign three parameters in the query.

It means that the url must be https://yourdomain.com/api/values?timestamp=xxx&nonce=yyy&sign=zzz

Most of the time, we will use Swagger as our document. How can we document those parameters in Swagger without adding them in each action?

Here I will use ASP.NET Core 3.1 to introduce the concept.

How to do this?
Create a new Web API project, and edit the csproj file, add the following content in it.
<ItemGroup> 
    <PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0" /> 
</ItemGroup> 
 
<PropertyGroup> 
    <GenerateDocumentationFile>true</GenerateDocumentationFile> 
    <NoWarn>$(NoWarn);1591</NoWarn> 
</PropertyGroup> 


Swashbuckle provides a feature named operation filter that can help us to do that job.

We can add those three additional parameters in our custom operation filter, so that we do not need to add them in each action.

Here is the sample code demonstration.
using Microsoft.AspNetCore.Mvc.Controllers; 
using Microsoft.OpenApi.Models; 
using Swashbuckle.AspNetCore.SwaggerGen; 
using System.Collections.Generic; 
 
public class AddCommonParameOperationFilter : IOperationFilter 

    public void Apply(OpenApiOperation operation, OperationFilterContext context) 
    { 
        if (operation.Parameters == null) operation.Parameters = new List<OpenApiParameter>(); 
 
        var descriptor = context.ApiDescription.ActionDescriptor as ControllerActionDescriptor; 
 
        if (descriptor != null && !descriptor.ControllerName.StartsWith("Weather")) 
        { 
            operation.Parameters.Add(new OpenApiParameter() 
            { 
                Name = "timestamp", 
                In = ParameterLocation.Query, 
                Description = "The timestamp of now", 
                Required = true 
            }); 
 
            operation.Parameters.Add(new OpenApiParameter() 
            { 
                Name = "nonce", 
                In = ParameterLocation.Query, 
                Description = "The random value", 
                Required = true 
            }); 
 
            operation.Parameters.Add(new OpenApiParameter() 
            { 
                Name = "sign", 
                In = ParameterLocation.Query, 
                Description = "The signature", 
                Required = true 
            }); 
        } 
    } 


NOTE
For showing the difference, we only add those parameters whose controller name does not start with Weather.

By the way, if you have any other parameters or conditions, add them yourself.

Then, we will configure Swagger in Startup class.
public class Startup 

    public void ConfigureServices(IServiceCollection services) 
    { 
        services.AddSwaggerGen(c => 
        { 
            // sepcify our operation filter here. 
            c.OperationFilter<AddCommonParameOperationFilter>(); 
 
            c.SwaggerDoc("v1", new OpenApiInfo 
            { 
                Version = "v1.0.0", 
                Title = $"v1 API", 
                Description = "v1 API", 
                TermsOfService = new Uri("https://www.c-sharpcorner.com/members/catcher-wong"), 
                Contact = new OpenApiContact 
                { 
                    Name = "Catcher Wong", 
                    Email = "[email protected]", 
                }, 
                License = new OpenApiLicense 
                { 
                    Name = "Apache-2.0", 
                    Url = new Uri("https://www.apache.org/licenses/LICENSE-2.0.html") 
                } 
            }); 
        }); 
 
        // other.... 
    } 

 
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 
    { 
        app.UseSwagger(c => 
        { 
        }); 
        app.UseSwaggerUI(c => 
        { 
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "v1 API"); 
        }); 
 
        // other.... 
    } 


Here is the result.


The controller name that doesn't start with `Weather` will contain those three parameters.

This article showed you a sample of how to add custom request parameters in Swagger using ASP.NET Core 3.1 and Swashbuckle.AspNetCore 5.0.0.



European ASP.NET Core Hosting :: Label, TextArea and Image Tag Helper In ASP.NET Core 3.1

clock February 11, 2020 11:55 by author Peter

In this blog, we will discuss 3 tag helpers: Label, Textarea and Image Tag Helper. We will also discuss how to use them in application with an example.

Label Tag Helper: The label tag helper is used for text labels in an application. It renders as an HTML label tag.
Textarea Tag Helper: The Textarea tag helper is used for Textarea of description in the application. It renders as an HTML Textarea tag.
Image Tag Helper: The Image Tag Helper renders as an HTML img tag. It is used to display images in the core applications. It provides cache-busting behavior for static image files. It has scr and asp-append-version which is set to true.

Step 1 Create an ASP.NET web application project in Visual Studio 2019.
Step 2 Create a class employee under the Models folder.
using System.ComponentModel.DataAnnotations; 
 
namespace LabelTextareaImageTagHelper__Demo.Models 

    public class Employee 
    { 
        [Key] 
        public int Id { get; set; } 
 
        [Required] 
        public string Name { get; set; } 
 
        [Required] 
        public string Image { get; set; } 
 
        [Required] 
        [MinLength(10)] 
        [MaxLength(255)] 
        public string Description { get; set; } 
    } 


Step 3 Now open index view from views than Home folder.
Step 4 Add model on top of the view to retrieve property of model class.
@model LabelTextareaImageTagHelper__Demo.Models.Employee  
Step 5 Create images folder in wwwroot folder copy and paste some image to display it on browser.
<div class="form-group"> 
   <label asp-for="Name" class="control-label"></label> 
   <input asp-for="Name" class="form-control" /> 
</div> 

<div class="form-group"> 
   <label asp-for="Image" class="control-label"></label> 
   <img src="~/images/855211650_154321.jpg" asp-append-version="true" height="150" width="150" class="img-thumbnail" /> 
</div> 

<div class="form-group"> 
   <label asp-for="Description" class="control-label"></label> 
   <textarea asp-for="Description" class="form-control"></textarea> 
</div>


This is how it renders in browser:
<textarea class="form-control" data-val="true" data-val-maxlength="The field Description must be a string or array type with a maximum length of '255'." data-val-maxlength-max="255" data-val-minlength="The field Description must be a string or array type with a minimum length of '10'." data-val-minlength-min="10" data-val-required="The Description field is required." id="Description" maxlength="255" name="Description"></textarea> 




European ASP.NET 3.1 Core Hosting :: How to Only Allow Numbers in a Text Box using jQuery?

clock February 4, 2020 11:05 by author Peter

This tutorial explains how to only allow a number in textbox using jQuery.  If you simply add the 'numberonly' class to the text control, then it will only allow numbers.

Code
$(document).ready(function () {   
   
            $('.numberonly').keypress(function (e) {   
   
                var charCode = (e.which) ? e.which : event.keyCode   
   
                if (String.fromCharCode(charCode).match(/[^0-9]/g))   
   
                    return false;                       
   
            });   
   
        });  
 



European ASP.NET Core Hosting :: ViewComponent In ASP.NET Core

clock January 28, 2020 11:09 by author Peter

ViewComponent was introduced in ASP.NET Core MVC. It can do everything that a partial view can and can do even more. ViewComponents are completely self-contained objects that consistently render html from a razor view. ViewComponents are very powerful UI building blocks of the areas of application which are not directly accessible for controller actions. Let's suppose we have a page of social icons and we display icons dynamically. We have separate settings for color, urls and names of social icons and we have to render icons dynamically.
 
Previously this kind of thing was achieved by HtmlHelpers and child actions but now it is very easy to use ViewComponent for this purpose. It is very easy to create your dynamic elements in a ViewCompnent and render in a view.
 
Creating a ViewComponent?
Step 1
Create a new ASP.NET Core MVC application and run that application. You can see an empty page like the following,

Step 2
We have to display data dynamically. In real scenarios dynamic data mostly comes from the database but for our application we do not use a database and we will create a class to generate fome data. So let's create a class. Add a class with name SocialIcon and add the following fields and methods in it,
    public class SocialIcon 
        { 
            public int ID { get; set; } 
            public string IconName { get; set; } 
            public string IconBgColor { get; set; } 
            public string IconTargetUrl { get; set; } 
            public string IconClass { get; set; } 
     
            public static List<SocialIcon> AppSocialIcons() 
            { 
                List<SocialIcon> icons = new List<SocialIcon>(); 
                icons.Add(new SocialIcon { ID = 1, IconName = "Google", IconBgColor = "#dd4b39",IconTargetUrl="www.google.com", IconClass="fa fa-google" }); 
                icons.Add(new SocialIcon { ID = 2, IconName = "Facebook", IconBgColor = "#3B5998", IconTargetUrl="www.facebook.com", IconClass="fa fa-facebook" }); 
                icons.Add(new SocialIcon { ID = 3, IconName = "Linked In", IconBgColor = "#007bb5", IconTargetUrl = "www.linkedin.com", IconClass= "fa fa-fa-linkedin" }); 
                icons.Add(new SocialIcon { ID = 4, IconName = "YouTube", IconBgColor = "#007bb5", IconTargetUrl = "www.youtube.com", IconClass="fa fa-youtube" }); 
                icons.Add(new SocialIcon { ID = 5, IconName = "Twitter", IconBgColor = "#55acee", IconTargetUrl = "www.twitter.com",IconClass="fa fa-twitter" }); 
     
                return icons; 
            } 
        } 


Step 3
Add a ViewComponent class with name SocialLinksViewComponent. (Don't forget to add ViewComponent with name, in our application we will use it with name SocialLinks and by writing ViewComponent with its name system will understand that it is ViewComponent and will be handled accordingly).

Step 4
ViewComponents are generated from a C# class derived from a base class ViewComponent and are typically associated with a Razor files to generate markup. Just like controllers, ViewComponents also support constructor injection. To implement SocialLinksViewComponent add the following code in your class that you have just created:
    public class SocialLinksViewComponent : ViewComponent 
       { 
           List<SocialIcon> socialIcons = new List<SocialIcon>(); 
           public SocialLinksViewComponent() 
           { 
               socialIcons = SocialIcon.AppSocialIcons(); 
           } 
     
           public async Task<IViewComponentResult> InvokeAsync() 
           { 
               var model = socialIcons; 
               return await Task.FromResult((IViewComponentResult)View("SocialLinks", model)); 
           } 
     
       } 


We created a class and added a List of SocialIcon class. In constructor we loaded our list with data (it is not mandatory to add in constructor you can add data in InvokeAsync method as well and there will be no need of constructor). It will return data in our model object and will render markup in Razor View SocialLinks.
 
Step 5
We added a folder in Views > Shared with the name Components (it should have Components name). And will added a folder SocialLinks in this folder we created a Razor View with name SocialLinks.cshtml. Do the same and add the following code in Razor View,
    @model IList<ViewComponentApp.Models.SocialIcon>   
       
    <div class="col-md-12" style="padding-top:50px;">   
        @foreach (var icon in Model)   
        {   
            <a style="background:@icon.IconBgColor" href="@icon.IconTargetUrl">   
                <i class="@icon.IconClass"></i>   
                @icon.IconName   
            </a>   
        }   
    </div>    


Step 6
Now we have implemented our ViewComponent and added markup html in our coresponding Razor View. Now we will call this ViewComponent in our desired page where it is needed. I am calling it on Index.cshtml page you can use it anywhere in the application with just this following code,
    @(await Component.InvokeAsync("SocialLinks")) 

This above code snippet is the way we can call a ViewComponent in our Razor Views. It will render the desired markup. You can also pass parameters in ViewComponents as following,
    @(await Component.InvokeAsync("SocialLinks", new { IconsToShow = 5 })) 

This is how we can pass parameters. But in our application we are not passing any parameters so we will use the snippet above. So code in our Index.cshtml page will look like this,
    @{   
        ViewData["Title"] = "Home Page";   
    }   
    <style>   
        a {   
            padding: 5px;   
            margin: 5px;   
            color: white;   
        }   
       
        .main-div {   
            margin-bottom: 20px;   
            padding-bottom: 20px;   
        }   
    </style>   
       
    <div class="text-center main-div">   
        <h1 class="display-4">Welcome</h1>   
        <h3>View Component Example</h3>   
       
        @(await Component.InvokeAsync("SocialLinks", new { IconsToShow = 5 }))   
       
    </div>    

Step 7
Run the application. After successfully running the application you will see the following output,

You can see that our ViewComponent is rendered on our Index.cshtml page. Similarly this can be rendered on any page in application using the same call that we used on Index.cshtml page. 

 



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