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 :: 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.");  
        }  
    }  

 



European ASP.NET Core Hosting - HostForLIFE.eu :: 9 Tips to Increase Your ASP.NET Core 3.0 Applications

clock March 31, 2020 09:56 by author Scott

Performance is very important; it is a major factor for the success of any web application. ASP.NET Core 3.0 includes several enhancements that scale back memory usage and improve turnout. In this blog post, I provide 10 tips to help you improve the performance of ASP.NET Core 3.0 applications by doing the following:

Avoid synchronous and use asynchronous

Try to avoid synchronous calling when developing ASP.NET Core 3.0 applications. Synchronous calling blocks the next execution until the current execution is completed. While fetching data from an API or performing operations like I/O operations or independent calling, execute the call in an asynchronous manner.

Avoid using Task.Wait and Task.Result, and try to use await. The following code shows how to do this.

public class WebHost
{
    public virtual async Task StartAsync(CancellationToken cancellationToken = default)
    { 

        // Fire IHostedService.Start
        await _hostedServiceExecutor.StartAsync(cancellationToken).ConfigureAwait(false); 

        // More setup
        await Server.StartAsync(hostingApp, cancellationToken).ConfigureAwait(false); 

        // Fire IApplicationLifetime.Started
        _applicationLifetime?.NotifyStarted(); 

        // Remaining setup
    }
}

Entity Framework 3.0 Core also provides a set of async extension methods, similar to LINQ methods, that execute a query and return results.

Asynchronous querying

Asynchronous queries avoid blocking a thread while the query is executed in the database. Async queries are important for quick, responsive client applications.

Examples:

  • ToListAsync()
  • ToArrayAsync()
  • SingleAsync()

public async Task<List> GetBlogsAsync()
{
    using (var context = new BloggingContext())
    {
        return await context.Blogs.ToListAsync();
    }
}

Asynchronous saving

Asynchronous saving avoids a thread block while changes are written to the database. It provides DbContext.SaveChangesAsync() as an asynchronous alternative to DbContext.SaveChanges().

public static async Task AddBlogAsync(string url)
{
    using (var context = new BloggingContext())
    {
        var blogContent = new BlogContent { Url = url };
        context.Blogs.Add(blogContent);
        await context.SaveChangesAsync();
    }
}

Optimize data access

Improve the performance of an application by optimizing its data access logic. Most applications are totally dependent on a database. They have to fetch data from the database, process the data, and then display it. If it is time-consuming, then the application will take much more time to load.

Recommendations:

  • Call all data access APIs asynchronously.
  • Don’t try to get data that is not required in advance.
  • Try to use no-tracking queries in Entity Framework Core when accessing data for read-only purposes.
  • Use filter and aggregate LINQ queries (with .Where, .Select, or .Sum statements), so filtering can be performed by the database.

You can find approaches that may improve performance of your high-scale apps in the new features of EF Core 3.0.

Use response caching middleware

Middleware controls when responses are cacheable. It stores responses and serves them from the cache. It is available in the Microsoft.AspNetCore.ResponseCaching package, which was implicitly added to ASP.NET Core.

In Startup.ConfigureServices, add the Response Caching Middleware to the service collection.

public void ConfigureServices(IServiceCollection services)
{
    services.AddResponseCaching();
    services.AddRazorPages();
}

Use JSON serialization

ASP.NET Core 3.0 uses System.Text.Json for JSON serialization by default. Now, you can read and write JSON asynchronously. This improves performance better than Newtonsoft.Json. The System.Text.Json namespace provides the following features for processing JSON:

  • High performance.
  • Low allocation.
  • Standards-compliant capabilities.

  • Serializing objects to JSON text and deserializing JSON text to objects.

Reduce HTTP requests

Reducing the number of HTTP requests is one of the major optimizations. Cache the webpages and avoid client-side redirects to reduce the number of connections made to the web server.

Use the following techniques to reduce the HTTP requests:

  • Use minification.
  • Use bundling.
  • Use sprite images.

By reducing HTTP requests, these techniques help pages load faster.

Use exceptions only when necessary

Exceptions should be rare. Throwing and catching exceptions will consume more time relative to other code flow patterns.

  • Don’t throw and catch exceptions in normal program flow.

  • Use exceptions only when they are needed.

Use response compression

Response compression, which compresses the size of a file, is another factor in improving performance. In ASP.NET Core, response compression is available as a middleware component.

Usually, responses are not natively compressed. This typically includes CSS, JavaScript, HTML, XML, and JSON.

  • Don’t compress natively compressed assets, such as PNG files.
  • Don’t compress files with a size of 150-1,000 bytes.
  • Don’t compress small files; it may produce a compressed file larger than the uncompressed file.

Package: Microsoft.AspNetCore.ResponseCompression is implicitly included in ASP.NET Core apps.

The following sample code shows how to enable Response Compression Middleware for the default MIME types and compression providers.

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddResponseCompression();
    }
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseResponseCompression();
    }
}

These are the providers:

public void ConfigureServices(IServiceCollection services)
{
    services.AddResponseCompression(options =>
    {
        options.Providers.Add<BrotliCompressionProvider>();
        options.Providers.Add<GzipCompressionProvider>();
        options.Providers.Add<CustomCompressionProvider>();
        options.MimeTypes =
            ResponseCompressionDefaults.MimeTypes.Concat(
                new[] { "image/svg+xml" });
    });
}

HttpContext accessibility improvements

HttpContext accessibility is only valid as long as there is an active HTTP request in ASP.NET Core. Here are some suggestions for accessing HttpContext from Microsoft’s documentation:

Client-side improvements

Client-side optimization is one important aspect of improving performance. When creating a website using ASP.Net Core, consider the following tips:

Bundling

Bundling combines multiple files into a single file, reducing the number of server requests. You can use multiple individual bundles in a webpage.

Minification

Minification removes unnecessary characters from code without changing any functionality, also reducing file size. After applying minification, variable names are shortened to one character and comments and unnecessary whitespace are removed.

Loading JavaScript at last

Load JavaScript files at the end. If you do that, static content will show faster, so users won’t have to wait to see the content.

Use a content delivery network

Use a content delivery network (CDN) to load static files such as images, JS, CSS, etc. This keeps your data close to your consumers, serving it from the nearest local server.

Conclusion

Now you know 10 tips to help improve the performance of ASP.NET Core 3.0 applications. I hope you can implement most of them in your development.

 



European ASP.NET Core Hosting - HostForLIFE.eu :: How to Use AutoMapper with ASP.NET Core 3

clock March 19, 2020 09:20 by author Scott

AutoMapper is well known in the .NET community. It bills itself as "a simple little library built to solve a deceptively complex problem - getting rid of code that maps one object to another," and it does the job nicely.

In the past, I've used it exclusively with ASP.NET APIs. However, the method for utilizing it via dependency injection has changed. So let's review how to get started, how to define mappings and how to inject our mappings into ASP.NET Core APIs.

Getting Started

Like most .NET libraries, we can install the AutoMapper package from Nuget.

Install-Package AutoMapper

For our purposes, we'll focus on two classes that are related; User and UserDTO.

public class User
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string FavoriteFood { get; set; }
    public DateTime BirthDate { get; set; }
}

public class UserDTO
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public int BirthYear { get; set; }
}

These classes will serve as source and destination types that we can work with.

Default Mappings

Without specific configuration, AutoMapper will match properties based on their name. By default, it will ignore null reference exceptions when mapping source and destination types. Below is a snippet mapping the source and destination types using the default configuration.

var config = new MapperConfiguration(cfg => cfg.CreateMap<User, UserDTO>());

var user = new User()
{
    Id = Guid.NewGuid(),
    Name = "Wayne Curry",
    FavoriteFood = "Sushi",
    BirthDate = new DateTime(1986, 10, 12)
};

var mapper = config.CreateMapper();
UserDTO userDTO = mapper.Map<UserDTO>(user);

The above will create a UserDTO object with an Id and Name that matches the original user object, but no error is thrown as a result of not having the FavoriteFood property on the UserDTO type. Also, the BirthYear property of the UserDTO will be zero.

Custom Mappings

We can use projection to translate properties as they are mapped. For instance, the code snippet below shows how we can map the BirthDate property of the User type to the BirthYear property of the UserDTO type.

var config = new MapperConfiguration(cfg =>
    cfg.CreateMap<User, UserDTO>()
        .ForMember(dest => dest.BirthYear,
                   opt => opt.MapFrom(src => src.BirthDate.Year));

var user = new User()
{
    Id = Guid.NewGuid(),
    Name = "Wayne Curry",
    FavoriteFood = "Sushi",
    BirthDate = new DateTime(1986, 10, 12)
};

var mapper = config.CreateMapper();
UserDTO userDTO = mapper.Map<UserDTO>(user);

The resulting userDTO object will be similar to our first example, but this time it will
include the BirthYear property of 2000.

Profiles

A clean way to organize and maintain our mapping configurations is with profiles. Many times these Profile classes will encapsulate business areas (e.g. Ordering, Shipping). To start, we'll create a class that inherits from Profile and put the configuration in the constructor.

public class UserManagementProfile : Profile
{
    public UserManagementProfile()
    {
        CreateMap<User, UserDTO>()
            .ForMember(dest => dest.BirthYear,
            opt => opt.MapFrom(src => src.BirthDate.Year));

        // Configurations for other classes in this business
        // area can be included here as well, like below:

        // CreateMap<Role, RoleDTO>();
        // CreateMap<Permission, PermissionDTO>();
    }
}

For added isolation, we can create a project just for our Profile configurations. Using profiles helps us keep configurations more manageable as our application grows.

Dependency Injection

Dependency injection is baked into ASP.NET Core, but to use AutoMapper with it we'll need additional configuration and an additional Nuget package.

Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection

Register AutoMapper

Once installed, we can define the configuration using profiles. In the Startup.ConfigureServices method, we can use the AddAutoMapper extension method on the IServiceCollection object as shown below:

// By Marker
services.AddAutoMapper(typeof(ProfileTypeFromAssembly1) /*, ...*/);

// or by Assembly
services.AddAutoMapper(profileAssembly1, profileAssembly2 /*, ...*/);

Inject AutoMapper

With AutoMapper registered and its configurations set, we can now inject an IMapper into our controllers.

public class UsersController
{
    private readonly IMapper _mapper;

    public UsersController(IMapper mapper) => _mapper = mapper;

    // use _mapper.Map
}

With the IMapper we can map our objects to their DTO equivalents using the .Map method.

Wrap It Up

Now that ASP.NET Core is injecting AutoMapper to our controllers, we can add configurations to our profiles or create new profiles for new business areas and still map appropriately without further configuration.

Of course, we didn't cover all of the features of AutoMapper so I'd suggest checking out their documentation for more information about their capabilities. Hopefully this post gave you enough information to start trying AutoMapper yourself. Let me know in the comments how you use AutoMapper in your applications.



European ASP.NET Core Hosting :: How to Use AutoMapper in Asp.Net Core Application

clock December 10, 2019 11:46 by author Scott

This is only brief tutorial about how to use AutoMapper in Asp Net Core 3.0 application. Automapper is a very popular Object-to-Object mapping library that can be used to map objects.

How to use automapper in Asp.Net Core 3.0 application

Let’s see how to use automapper in Asp Net Core 3.0 application using a very simple example.

1. First step you need to do is please make sure you install Asp.net Core 3.0 application à Create a new project button à then choose “ASP.NET Core Web Application” template à click “Next” button and then enter your Project name. Please see the image below for further information

 

2. Install AutoMapper in Asp.Net Core 3.0 Application 

Now, in this step, we will install AutoMapper in our project. So, go to visual studio and then go to “Tools” from the menu and then select “NuGet Package Manager” and then choose “Manager NuGet Packages for Solution”. Now, go to “Browse” tab and then install this below package as you do see below in the screenshot.

Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection

3. Configure AutoMapper in Asp.net Core 3.0 Application

Go to project folder structure, and then go to Startup class and then add some changes as you do see below in the code file’s Line # 11 and Line # 26.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using AutoMapper;
namespace AspNetCore3AutoMapper
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

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

        }
    }
}

4. Create a Model Class and Data Transfer Object Class

Now, in this step , we will create two classes. One is Model class and the other one is Dto(Data Transfer Object) class. So, go to Models’ folder and then right click on the folder name and then add a new class with the name of “Employee” and then write some properties as you do see below in the code.

public class Employee
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Department { get; set; }
    }

Now, again add a new class with the name of “EmployeeDto” as you do see below in the file.

public class EmployeeDto
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Department { get; set; }
    }

5. Add relation of Employee class with EmployeeDto class

Now, in this step, we will see how to add relation between a domain class and a Dto class. So, again add a new class (E.g. AutoMapping.cs) and then write some code as you do see below in the code.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;

namespace AspNetCoreAutoMapper.Models
{
    public class AutoMapping : Profile
    {
        public AutoMapping()
        {
            CreateMap<Employee, EmployeeDto>();
        }
    }
}

Let’s understand the above code.

Line # 9: In this line, we are inheriting AutoMapping class from Profile.

Line # 13: In this line, we are mapping our Employee and EmployeeDto Classes.

6. Map Employee class with EmployeeDto Controller

We will see how to map Employee class with EmployeeDto class within the Home Controller. So, go to HomeController and then go to Index method and then write some code as you do see below in the file.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using AspNetCore3AutoMapper.Models;
using AutoMapper;

namespace AspNetCore3AutoMapper.Controllers
{
    public class HomeController : Controller
    {
        private readonly IMapper _mapper;
        public HomeController(IMapper mapper)
        {
            _mapper = mapper;
        }
        public IActionResult Index()
        {
            var empObj = new Employee();
            empObj.Id = 1;
            empObj.Name = "Scott";
            empObj.Department = "MM";
            var employeeDto = _mapper.Map<EmployeeDto>(empObj);
            return View(employeeDto);
        }
    }
}

Let’s understand the above code.

Line # 15 to 19: In this block of code, we are injecting IMapper interface. This will help us to use our configured mappings.

Line # 22 to 25: In this block of code, we are initializing Employee object.

Line # 26: In this line, we are using IMapper interface that we have injected into our constructor to call the Map method. And we are giving the type that we want to map and the object that we want to map from.

Line # 27: In this line, we are returning the EmployeeDto object to the view.

Now, go to Index view and access the returning values from the Index method as you do see below in the file.

@model EmployeeDto
@{
    ViewData["Title"] = "Home Page";
}
<div>
    <h1>ID: @Model.Id</h1>
    <h1>Name: @Model.Name</h1>
    <h1>Department: @Model.Department</h1>
</div>

Now, run your project by pressing f5 and then you will see the output

Or you can install this package by using this below command in Package Manager Console as you do see below in the screenshot.



European ASP.NET Core Hosting :: Error When Published ASP.NET Core? See Below Tips!

clock November 5, 2019 05:38 by author Scott

At the past few years, we have discussed about common error that you can find when published .NET Core, the most common error is 502.5 – process failure error.

Startup errors with ASP.NET Core don’t provide much information either, at least not in a production environment. Here are 7 tips for understanding and fixing those errors.

1. There are two types of startup errors.

There are unhandled exceptions originating outside of the Startup class, and exceptions from inside of Startup. These two error types can produce different behavior and may require different troubleshooting techniques.

2. ASP.NET Core will handle exceptions from inside the Startup class.

If code in the ConfigureServices or Configure methods throw an exception, the framework will catch the exception and continue execution.

Although the process continues to run after the exception, every incoming request will generate a 500 response with the message “An error occurred while starting the application”.

Two additional pieces of information about this behavior:

- If you want the process to fail in this scenario, call CaptureStartupErrors on the web host builder and pass the value false.

- In a production environment, the “error occurred” message is all the information you’ll see in a web browser. The framework follows the practice of not giving away error details in a response because error details might give an attacker too much information. You can change the environment setting using the environment variable ASPNETCORE_ENVIRONMENT, but see the next two tips first. You don’t have to change the entire environment to see more error details.

3. Set detailedErrors in code to see a stack trace.

The following bit of code allows for detailed error message, even in production, so use with caution.

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
           .CaptureStartupErrors(true) // the default
           .UseSetting("detailedErrors", "true")
           .UseStartup<Startup>();

4. Alternatively, set the ASPNETCORE_DETAILEDERRORS environment variable.

Set the value to true and you’ll also see a stack trace, even in production, so use with caution.

5. Unhandled exceptions outside of the Startup class will kill the process.

Perhaps you have code inside of Program.cs to run schema migrations or perform other initialization tasks which fail, or perhaps the application cannot bind to the desired ports. If you are running behind IIS, this is the scenario where you’ll see a generic 502.5 Process Failure error message.

These types of errors can be a bit more difficult to track down, but the following two tips should help.

6. For IIS, turn on standard output logging in web.config.

If you are carefully logging using other tools, you might be able to capture output there, too, but if all else fails, ASP.NET will write exception information to stdout by default. By turning the log flag to true, and creating the output directory, you’ll have a file with exception information and a stack trace inside to help track down the problem.

The following shows the web.config file created by dotnet publish and is typically the config file in use when hosting .NET Core in IIS. The attribute to change is the stdoutLogEnabled flag.

<system.webServer>
  <handlers>
    <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />

  </handlers>
  <aspNetCore processPath="dotnet" arguments=".\codes.dll"
              stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" />
</system.webServer>

Important: Make sure to create the logging output directory.

Important: Make sure to turn logging off after troubleshooting is complete.

7. Use the dotnet CLI to run the application on your server.

If you have access to the server, it is sometimes easier to go directly to the server and use dotnet to witness the exception in real time. There’s no need to turn on logging or set and unset environment variables.

Summary

Debugging startup errors in ASP.NET Core is a simple case of finding the exception. In many cases, #7 is the simplest approach that doesn’t require code or environment changes. FYI, we also have support latest ASP.NET Core on our hosting environment. Feel free to visit our site at https://www.hostforlife.eu.



European ASP.NET Core 3 Hosting :: Custom JSONConverter ASP.NET Core 3

clock October 17, 2019 07:17 by author Scott

With the introduction of ASP.NET Core 3.0 the default JSON serializer has been changed from Newtonsoft.Json to System.Text.Json. For projects and libraries switching to the new JSON serializer this change means more performance and the opportunity to rewrite our JsonConverters.

Serialization of concrete classes

Let's start with a simple one that can (de)serialize a concrete class Category. In our example we (de)serialize the property Name only.

public class Category
{
   public string Name { get; }

   public Category(string name)
   {
      Name = name;
   }
}

To implement a custom JSON converter we have to derive from the generic class JsonConverter<T> and to implement 2 methods: Read and Write.

public class CategoryJsonConverter : JsonConverter<Category>
{
   public override Category Read(ref Utf8JsonReader reader,
                                 Type typeToConvert,
                                 JsonSerializerOptions options)
   {
      var name = reader.GetString();

      return new Category(name);
   }

   public override void Write(Utf8JsonWriter writer,
                              Category value,
                              JsonSerializerOptions options)
   {
      writer.WriteStringValue(value.Name);
   }
}

The method Read is using the Utf8JsonReader to fetch a string, i.e. the name, and the method Write is writing a string using an instance of Utf8JsonWriter.

In both cases (i.e. during serialization and deserialization) the converter is not being called if the value is null so I skipped the null checks. The .NET team doesn't do null checks either, see JsonKeyValuePairConverter<TKey, TValue>.

Let's test the new JSON converter. For that we create an instance of JsonSerializerOptions and add our CategoryJsonConverter to the Converters collection. Next, we use the static class JsonSerializer to serialize and to deserialize an instance of Category.

Category category = new Category("my category");

var serializerOptions = new JsonSerializerOptions
{
    Converters = { new CategoryJsonConverter() }
};

// json = "my category"
var json = JsonSerializer.Serialize(category, serializerOptions);

// deserializedCategory.Name = "my category"
var deserializedCategory = JsonSerializer.Deserialize<Category>(json, serializerOptions);

Serialization of generic classes

The next example is slightly more complex. The property we are serializing is a generic type argument, i.e. we can't use methods like reader.GetString() or writer.WriteStringValue(name) because we don't know the type at compile time.

In this example I've changed the class Category to a generic type and renamed the property Name to Key:

public class Category<T>
{
   public T Key { get; }

   public Category(T key)
   {
      Key = key;
   }
}

For serialization of the generic property Key we need to fetch a JsonSerializer<T> using the instance of JsonSerializerOptions.

public class CategoryJsonConverter<T> : JsonConverter<Category<T>>
{
   public override Category<T> Read(ref Utf8JsonReader reader,
                                    Type typeToConvert,
                                    JsonSerializerOptions options)
   {
      var converter = GetKeyConverter(options);
      var key = converter.Read(ref reader, typeToConvert, options);

      return new Category<T>(key);
   }

   public override void Write(Utf8JsonWriter writer,
                              Category<T> value,
                              JsonSerializerOptions options)
   {
      var converter = GetKeyConverter(options);
      converter.Write(writer, value.Key, options);
   }

   private static JsonConverter<T> GetKeyConverter(JsonSerializerOptions options)
   {
      var converter = options.GetConverter(typeof(T)) as JsonConverter<T>;

      if (converter is null)
         throw new JsonException("...");

      return converter;
   }
}

The behavior of the generic JSON converter is the same as before especially if the Key is of type string.

Deciding the concrete JSON converter at runtime

Having several categories with different key types, say, string and int, we need to register them all with the JsonSerializerOptions.

var serializerOptions = new JsonSerializerOptions
                        {
                           Converters =
                           {
                              new CategoryJsonConverter<string>(),
                              new CategoryJsonConverter<int>()
                           }
                        };

If the number of required CategoryJsonConverters grows to big or the concrete types of the Key are not known at compile time then this approach is not an option. To make this decision at runtime we need to implement a JsonConverterFactory. The factory has 2 method: CanConvert(type) that returns true if the factory is responsible for the serialization of the provided type; and CreateConverter(type, options) that should return an instance of type JsonConverter.

public class CategoryJsonConverterFactory : JsonConverterFactory
{
   public override bool CanConvert(Type typeToConvert)
   {
      if (!typeToConvert.IsGenericType)
         return false;

      var type = typeToConvert;

      if (!type.IsGenericTypeDefinition)
         type = type.GetGenericTypeDefinition();

      return type == typeof(Category<>);
   }

   public override JsonConverter CreateConverter(Type typeToConvert,
                                                 JsonSerializerOptions options)
   {
      var keyType = typeToConvert.GenericTypeArguments[0];
      var converterType = typeof(CategoryJsonConverter<>).MakeGenericType(keyType);

      return (JsonConverter)Activator.CreateInstance(converterType);
   }
}

Now, we can remove all registrations of the CategoryJsonConverter<T> from the options and add the newly implemented factory.

Category<int> category = new Category<int>(42);

var serializerOptions = new JsonSerializerOptions
{
    Converters = { new CategoryJsonConverterFactory() }
};

// json = 42
var json = JsonSerializer.Serialize(category, serializerOptions);

// deserialized.Key = 42
var deserialized = JsonSerializer.Deserialize<Category<int>>(json, serializerOptions);

In the end the implementation of a custom converter for System.Text.Json is very similar to the one for Newtonsoft.Json. The biggest difference here is the non-existence of a non-generic JsonConverter but for that we've got the JsonConverterFactory.

Actually, there is a non-generic JsonConverter which is the base class of the JsonConverter<T> and the JsonConverterFactory but we cannot (and should not) use this class directly because its constructor is internal.



European ASP.NET Core Hosting :: Paging Using Repeater Control In ASP.NET With And Without Stored Procedure

clock October 16, 2019 11:06 by author Peter

By default, pagination is not enabled in a Repeater control. We have to write custom pager control to use paging in a Repeater control. Here, I will explain how to implement paging in Repeater control in ASP.NET with and without a stored procedure. I am using Visual Studio 2019 to create the application.

Step 1
First, we have to create a table “tblCustomers” to test the paging in the repeater control.
CREATE TABLE [dbo].[tblCustomers]( 
[Id] [int] NOT NULL, 
[Name] [nvarchar](50) NULL, 
[Company] [nvarchar](50) NULL, 
[Phone] [nvarchar](50) NULL, 
[Address] [nvarchar](50) NULL, 
[Country] [nvarchar](50) NULL, 
[Email] [nvarchar](50) NULL 


After creating the table, add some record to the table.

Step 2
Open Visual Studio and click on "Create a new project".
Select ASP.NET Web Application from templates and click on “Next”.
Then, give the project name as “AspRepeater” and then click “Create”.
Now, choose “Web Forms” from the template and click on “Create”.

ASP.NET Repeater Control without Stored Procedure

Step 3
Now, create a new weborm “RepeaterControl” and write the code following code in your “RepeaterControl.aspx” page.
Code for RepeaterControl.aspx page.
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="RepeaterControl.aspx.cs" Inherits=" AspRepeater.RepeaterControl" %> 

<!DOCTYPE html> 

<html xmlns="http://www.w3.org/1999/xhtml"> 
<head runat="server"> 
<title>Repeater Control without Stored Procedure</title> 
</head> 
<body> 
<form id="form1" runat="server"> 
    <div> 
        <asp:Repeater ID="Repeater2" runat="server"> 
            <HeaderTemplate> 
                <table id="tbDetails" style="width: 100%; border-collapse: collapse;" border="1" cellpadding="5" cellspacing="0"> 
                    <tr style="background-color: lightgray; height: 30px; color: black; text-align: center"> 
                        <th>Id</th> 
                        <th>Customer Name</th> 
                        <th>Company Name</th> 
                        <th>Phone</th> 
                        <th>Address</th> 
                        <th>E-Mail</th> 
                    </tr> 
            </HeaderTemplate> 
            <ItemTemplate> 
                <tr style="height: 25px;"> 
                    <td> 
                        <%#Eval("Id").ToString()%> 
                    </td> 
                    <td> 
                        <%#Eval("Name").ToString()%> 
                    </td> 
                    <td> 
                        <%#Eval("Company").ToString()%> 
                    </td> 
                    <td> 
                        <%#Eval("Phone").ToString()%> 
                    </td> 
                    <td> 
                        <%#Eval("Address").ToString()%>, <%#Eval("Country").ToString()%> 
                    </td> 
                    <td> 
                        <%#Eval("Email").ToString()%> 
                    </td>                         
                </tr> 
            </ItemTemplate> 
            <FooterTemplate> 
                </table> 
            </FooterTemplate> 
        </asp:Repeater> 
    </div> 
    <br /> 
    <div style="text-align:center"> 
        <asp:Repeater ID="Repeater1" runat="server" OnItemCommand="Repeater1_ItemCommand"> 
            <ItemTemplate> 
                <asp:LinkButton ID="lnkPage" 
                    Style="padding: 8px; margin: 2px; background: lightgray; border: solid 1px #666; color: black; font-weight: bold" 
                    CommandName="Page" CommandArgument="<%# Container.DataItem %>" runat="server" Font-Bold="True"><%# Container.DataItem %> 
                </asp:LinkButton> 
            </ItemTemplate> 
        </asp:Repeater> 
    </div> 
</form> 
</body> 
</html> 


Code for RepeaterControl.aspx.cs,
using System; 
using System.Collections; 
using System.Configuration; 
using System.Data; 
using System.Data.SqlClient; 
using System.Web.UI.WebControls; 

namespace AspRepeater 

public partial class RepeaterControl : System.Web.UI.Page 
{  
    private int iPageSize = 15; 

    protected void Page_Load(object sender, EventArgs e) 
    { 
        if (!IsPostBack) 
        { 
            GetCustomers(); 
        } 
    } 

    private void GetCustomers() 
    { 
        DataTable dtData = new DataTable(); 
        string conString = ConfigurationManager.ConnectionStrings["dbConnection"].ConnectionString; 
        SqlConnection sqlCon = new SqlConnection(conString); 
        sqlCon.Open(); 
        SqlCommand sqlCmd = new SqlCommand("Select * From tblCustomers", sqlCon); 
        SqlDataAdapter sqlDa = new SqlDataAdapter(sqlCmd); 
        sqlDa.Fill(dtData); 
        sqlCon.Close(); 

        PagedDataSource pdsData = new PagedDataSource(); 
        DataView dv = new DataView(dtData); 
        pdsData.DataSource = dv; 
        pdsData.AllowPaging = true; 
        pdsData.PageSize = iPageSize; 
        if (ViewState["PageNumber"] != null) 
            pdsData.CurrentPageIndex = Convert.ToInt32(ViewState["PageNumber"]); 
        else 
            pdsData.CurrentPageIndex = 0; 
        if (pdsData.PageCount > 1) 
        { 
            Repeater1.Visible = true; 
            ArrayList alPages = new ArrayList(); 
            for (int i = 1; i <= pdsData.PageCount; i++) 
                alPages.Add((i).ToString()); 
            Repeater1.DataSource = alPages; 
            Repeater1.DataBind(); 
        } 
        else 
        { 
            Repeater1.Visible = false; 
        } 
        Repeater2.DataSource = pdsData; 
        Repeater2.DataBind(); 
    } 
     
    protected void Repeater1_ItemCommand(object source, RepeaterCommandEventArgs e) 
    { 
        ViewState["PageNumber"] = Convert.ToInt32(e.CommandArgument); 
        GetCustomers(); 
    } 



ASP.NET Repeater Control with Stored Procedure

Step 4
By using a Stored Procedure, we can fetch only one-page records from the available records based on the page index. For example, if our table has 300 records and we need to display only 15 records per page, then we will fetch only 15 records based on the page index.

Script for the Stored Procedure,
CREATE PROCEDURE GetCustomer 
@PageIndex INT = 1, 
@PageSize INT = 15, 
@RecordCount INT OUTPUT 
AS 
BEGIN 
SET NOCOUNT ON; 
SELECT ROW_NUMBER() OVER(ORDER BY Id ASC)AS RowNumber,ID, 
Name,Company,Phone,Address,Country,Email 
INTO #Results FROM tblCustomers 
  
SELECT @RecordCount = COUNT(*) FROM #Results 
        
SELECT * FROM #Results WHERE RowNumber BETWEEN(@PageIndex -1) * @PageSize + 1  
AND (((@PageIndex -1) * @PageSize + 1) + @PageSize) - 1 
  
DROP TABLE #Results 
END 

Step 5
Now, create a new webform “RepeaterControl1” and write the following code in your “RepeaterControl1.aspx” page.

Code for RepeaterControl.aspx page.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="RepeaterControl1.aspx.cs" Inherits="AspRepeater.RepeaterControl1" %> 

<!DOCTYPE html> 

<html xmlns="http://www.w3.org/1999/xhtml"> 
<head runat="server"> 
<title>Repeater Control with Stored Procedure</title> 
</head> 
<body> 
<form id="form1" runat="server"> 
    <div> 
        <asp:Repeater ID="Repeater1" runat="server"> 
            <HeaderTemplate> 
                <table id="tbDetails" style="width: 100%; border-collapse: collapse;" border="1" cellpadding="5" cellspacing="0"> 
                    <tr style="background-color: lightgray; height: 30px; color: black; text-align: center"> 
                        <th>Id</th> 
                        <th>Customer Name</th> 
                        <th>Company Name</th> 
                        <th>Phone</th> 
                        <th>Address</th> 
                        <th>E-Mail</th> 
                    </tr> 
            </HeaderTemplate> 
            <ItemTemplate> 
                <tr style="height: 25px;"> 
                    <td> 
                        <%#Eval("Id").ToString()%> 
                    </td> 
                    <td> 
                        <%#Eval("Name").ToString()%> 
                    </td> 
                    <td> 
                        <%#Eval("Company").ToString()%> 
                    </td> 
                    <td> 
                        <%#Eval("Phone").ToString()%> 
                    </td> 
                    <td> 
                        <%#Eval("Address").ToString()%>, <%#Eval("Country").ToString()%> 
                    </td> 
                    <td> 
                        <%#Eval("Email").ToString()%> 
                    </td> 
                </tr> 
            </ItemTemplate> 
            <FooterTemplate> 
                </table> 
            </FooterTemplate> 
        </asp:Repeater> 
    </div> 
    <br /> 
    <div style="text-align:center"> 
        <asp:Repeater ID="Repeater2" runat="server" OnItemCommand="Repeater2_ItemCommand"> 
            <ItemTemplate> 
                <asp:LinkButton ID="lnkPage" 
                    Style="padding: 8px; margin: 2px; background: lightgray; border: solid 1px #666; color: black; font-weight: bold" 
                    CommandName="Page" CommandArgument="<%# Container.DataItem %>" runat="server" Font-Bold="True"><%# Container.DataItem %> 
                </asp:LinkButton> 
            </ItemTemplate> 
        </asp:Repeater> 
    </div> 
</form> 
</body> 
</html> 

Code for RepeaterControl1.aspx.cs.
using System; 
using System.Collections.Generic; 
using System.Configuration; 
using System.Data; 
using System.Data.SqlClient; 
using System.Web.UI.WebControls; 

namespace AspRepeater 

public partial class RepeaterControl1 : System.Web.UI.Page 

    private int iPageSize = 15; 
    protected void Page_Load(object sender, EventArgs e) 
    { 
        if (!IsPostBack) 
        { 
            this.GetCustomers(1); 
        } 
    } 

    private void GetCustomers(int iPageIndex) 
    { 
        string conString = ConfigurationManager.ConnectionStrings["dbConnection"].ConnectionString; 
        SqlConnection sqlCon = new SqlConnection(conString); 
        sqlCon.Open(); 
        SqlCommand sqlCmd = new SqlCommand("GetCustomer", sqlCon); 
        sqlCmd.CommandType = CommandType.StoredProcedure; 
        sqlCmd.Parameters.AddWithValue("@PageIndex", iPageIndex); 
        sqlCmd.Parameters.AddWithValue("@PageSize", iPageSize); 
        sqlCmd.Parameters.Add("@RecordCount", SqlDbType.Int, 4); 
        sqlCmd.Parameters["@RecordCount"].Direction = ParameterDirection.Output; 
        IDataReader iDr = sqlCmd.ExecuteReader(); 
        Repeater1.DataSource = iDr; 
        Repeater1.DataBind(); 
        iDr.Close(); 
        sqlCon.Close(); 
        int iRecordCount = Convert.ToInt32(sqlCmd.Parameters["@RecordCount"].Value); 

        double dPageCount = (double)((decimal)iRecordCount / Convert.ToDecimal(iPageSize)); 
        int iPageCount = (int)Math.Ceiling(dPageCount); 
        List<ListItem> lPages = new List<ListItem>(); 
        if (iPageCount > 0) 
        { 
            for (int i = 1; i <= iPageCount; i++) 
                lPages.Add(new ListItem(i.ToString(), i.ToString(), i != iPageIndex)); 
        } 
        Repeater2.DataSource = lPages; 
        Repeater2.DataBind(); 
    } 

    protected void Repeater2_ItemCommand(object source, RepeaterCommandEventArgs e) 
    { 
        int iPageIndex = Convert.ToInt32(e.CommandArgument); 
        GetCustomers(iPageIndex); 
    } 

 



European ASP.NET Core Hosting :: TextBox Autocomplete with .NET Core 3.0

clock October 11, 2019 11:56 by author Peter

.NET Core 3.0 is the latest version of .NET Core and now supports WinForms and WPF. This sample shows how you can perform fill data to Autocomplete TextBox in another thread without slow down the main UI (User Interface). With this sample, you can do a better user experience for the end-user.

TextBox Autocomplete
Autocomplete helps the user to search/type from a know list. In my application, I build a list to Autocomplete with > 10.000 items and is very fast even on slow computers.

Autocomplete is an old feature, but this POST will demonstrate how to perform his use to load data fastly already in NET Core 3.0.

When you fill a Collection, if you have a huge suggestion list, this will make the UI (User Interface) freezes. But if you process in another thread the UI will not have any issues.

More technical information you can have here.

How it works

Like the other POST what uses a delegate, here, we use another thread to load data and delegate to bind the Autocomplete Collection in the current UI thread.
using System;  
using System.Data.SqlClient;  
using System.Drawing;  
using System.Windows.Forms;  
 
namespace TextBoxWithAutoComplete  
{  
 
    /// <summary>  
    /// 10-10-2019  
    /// </summary>  
    public partial class Form1 : Form  
    {  
 
        private TextBox textBox1;  
        public Form1()  
        {  
            InitializeComponent();  
 
            textBox1 = new TextBox  
            {  
                Location = new Point(0, 0),  
                Size = new Size(100, 32),  
                Visible = true,  
                TabIndex = 0  
            };  
            Controls.Add(textBox1);  
 
            Load += Form1_Load;  
        }  
 
        public void Form1_Load(object sender, EventArgs e)  
        {  
            Show(); // You need to show the form to avoid a thread error  
 
            LoadData(); // Start to load Data  
        }  
 
        private SqlConnection GetConnection()  
        {  
            // Init your connection  
            var oCnn = new SqlConnection  
            {  
                ConnectionString = "YOUR_CONNECTION_STRING"  
            };  
            oCnn.Open();  
            return oCnn;  
        }  
 
 
        #region TreadSafeLoading  
        private delegate void UpdateUIDelegate(AutoCompleteStringCollection myCollection);  
 
        /// <summary>  
        /// Load Data - You can make public to load as you need  
        /// </summary>  
        private void LoadData()  
        => // Start this process in a new thread  
            new System.Threading.Thread(() => OutOfThreadProcess()).Start();  
        // You can start others, every one in a new thread!  
 
        /// <summary>  
        /// Start fill in another Thread  
        /// </summary>  
        private void OutOfThreadProcess()  
        {  
            // inialize the collection  
            var myCollection = new AutoCompleteStringCollection();  
            using var oCnn = GetConnection();  
 
            // Start your SQL Query  
            var cmd = new SqlCommand($"Select [FirstName] + ' ' + [LastName] as [contactName] From [AdventureWorks].[Person].[Contact] Order By [FirstName], [LastName]", oCnn);  
 
            // Read and fill the collection  
            using var reader = cmd.ExecuteReader();  
            while (reader.Read())  
                myCollection.Add(reader.GetString(0));  
 
            // Invoke in a UI thread  
            _ = Invoke(new UpdateUIDelegate(UpdateUIInvoke), myCollection);  
        }  
 
        /// <summary>  
        /// Current UI Thread threatment  
        /// </summary>  
        /// <param name="myCollection"></param>  
        private void UpdateUIInvoke(AutoCompleteStringCollection myCollection)  
        {  
            // Setup up in corrent UI Thread  
            textBox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend;  
            textBox1.AutoCompleteSource = AutoCompleteSource.CustomSource;  
            textBox1.AutoCompleteCustomSource = myCollection;  
#if (IS_TELERIK_RadTextBoxControl)  
            // If you use Telerik  
            // I found an issue in Telerik by Progress, without fix.  
            if (ParentForm != null)  
                ParentForm.FormClosing += new FormClosingEventHandler(UIFormClosing);  
#endif  
        }  
#if (IS_TELERIK_RadTextBoxControl)  
        private void UIFormClosing(object sender, FormClosingEventArgs e) => textBox1.AutoCompleteCustomSource = null;  
 
#endif  
        #endregion  
 
    }  
}  

Observation

When you use this technic may you receive errors if you run the new thread without fire the Show() method from the form, this occurs because the current window(form) hasn't the Handle initialized.

Conclusion
I design this technic when I upgrade to .NET Core 3 and develop a fix for the FileSystemWatcher event that fires in a new thread, so I took the same idea to make Autocomplete load collection works in a new thread.



European ASP.NET Core Hosting :: Knowing about WinForms and .NET Core 3.0

clock October 11, 2019 09:29 by author Scott

Desktop support for .NET Core 3.0 has been in preview for some time, it is slated to be released later this year. As per indicators by Microsoft, .NET Core will receive more updates compared to full .NET Framework, keeping this in mind, it makes sense to start thinking about migrating existing applications and creating new ones on .NET Core if the application still has some years to go.

Desktop support in .NET Core has not been completely migrated yet; however, it is possible to create and migrate WinForms applications using the preview bits. In this article, we'll consider the creation and migration of a WinForms application in .NET Core 3.0 that uses ComponentOne controls.

Creating a New .NET Core 3.0 Application

To create a new .NET Core 3.0 application, it's recommended to download VS 2019 and the nightly build of the .NET Core 3.0 SDK. Make sure that you’ve installed the .NET Framework 4.7.2 and .NET Core 2.1 development tools in the Visual Studio Installer. This software will be necessary whether you plan on creating a new project or migrating an existing one to .NET Core 3.0.

The simplest way to work with .NET Core 3.0 (for now) is to use dotnet.exe command line utility. It can be used to create a new project, add/restore dependencies, build, etc.

.NET Core 3 - Using x64 and x86 Versions

Visual Studio uses the appropriate version depending on your .NET Core 3 project’s target platform – x86 or x64. It uses last installed version for both platforms. So, if you intend to build your project for both platforms, you must download and install both platform SDK versions with the same version.

These are the typical paths for .NET Core 3 command line utility:

  • c:\Program Files\dotnet\dotnet.exe - for x64 version of .Net Core 3
  • c:\Program Files (x86)\dotnet\dotnet.exe- for x86 version of .Net Core 3

Let’s use x64 version of dotnet.exe to simplify it for further description.

Create a New Visual Studio Project

First, you’ll need to open the Visual Studio Developer Command Prompt to create a project through the command line. Currently, the tooling for Visual Studio is very limited in its support of .NET Core 3.0, so it’s easiest to create a project through the command line interface.

First, we’ll create the project:

“c:\Program Files\dotnet\dotnet.exe” **new** winforms -o TestAppWinFormsCore

Once this is finished, we’ll navigate into the project directory:

cd TestAppWinFormsCore

Finally, we can run the project to make sure that it works:

“c:\Program Files\dotnet\dotnet.exe” run

Now that the project has been created, we can use Visual Studio 2019 to open it and modify its contents. 

In the Visual Studio 2019, open the TestAppWinFormsCore.csproj file we just created.

You should see something like this in Visual Studio:

.NET Core 3.0 uses a new project type and has no design-time support currently, so the process of adding controls will be a little different than what you may be accustomed to. We need to add C1 libraries manually to the project to make use of them, also, we should add the controls manually to Form1.cs because of missing design-time support.

Because of this, let’s use a trick. We'll add the classic .NET Framework WinForms project in order to use its Form designer:

1. Right-click on Solution node and Add – New Project… - Windows Forms Desktop project (with .Net Framework, say version 4.0). The name of new project is by default WindowsFormsApp1.

2. Remove the existing Form1 from WindowsFormsApp1 project

3. Add Form1.cs from TestAppWinFoirmsCore project as link:

After that, the following view of Solution Explorer appears:

Now, we can edit Form1 form in the usual way:

Now, remove unneeded “Hello .NET Core!” label and add some C1 control, for example C1DockingTab:

Launch WindowsFormsApp1 application and observe C1DockingTab on Form1. But this will be a .Net Framework 4 application.

Adding C1DockingTab caused adding C1.Win.C1Command.4 reference to WindowsFormsApp1 project. Therefore, the same reference should be added to TestAppWinFormsCore project also. For this let’s take a look in the properties of the C1.Win.C1Command.4 reference (right-click – Properties…) and find the path to the assembly. It looks like C:\Program Files (x86)\ComponentOne\WinForms Edition\bin\v4.0\C1.Win.C1Command.4.dll. Add this reference to the TestAppWinFormsCore project (right-click on Dependencies – Add reference… - Browse… - choose C:\Program Files (x86)\ComponentOne\WinForms Edition\bin\v4.0\C1.Win.C1Command.4.dll).

You should be able to run the code at this point, though you’ll notice a ComponentOne nag screen since the TestAppWinFormsCore project doesn’t contain any licensing information.

We can correct this by adding a licenses.licx file to the project. To do so, right-click on TestAppWinFormsCore project and select Add -> Existing Items. And browse the licenses.licx file from WindowsFormsApp1/Properties folder.

Build and rerun the app and you should no longer see a nag screen.

And now this is a genuine .NET Core 3.0 WinForms app. You can see this in the Modules window. All system references are from C:\Program Files\dotnet... folder.

Migrating an Existing Project to .NET Core 3.0

It is possible to migrate an existing project to .NET Core 3.0, though the process may require a few more steps than you would expect. Also, before trying to migrate a project, it’s worth running Microsoft’s portability analyzer tool on the project you want to convert.

The tool can give you an idea (ahead of time) how compatible your project will be with .NET Core 3.0, and it points out potential problems you may run into (included unsupported APIs).

If you’ve made up your mind to try to migrate a project, it’s easiest to begin the process by creating a project through dotnet.exe as described above.Let’s look at the WeatherChart sample migration. This sample demonstrates the C1FlexChart control possibilities.

First, we’ll create a new DotNetCore3FlexChart project from the command line:

“c:\Program Files\dotnet\dotnet.exe” **new** winforms -o DotNetCore3FlexChart

Once this is finished, we’ll navigate into the project directory and open DotNetCore3FlexChart.csproj from Visual Studio 2019.

Next, add the WeatherChart project to the DotNetCore3FlexChart solution. WeatherChart project is placed in Documents\ComponentOne Samples\WinForms\C1FlexChart\CS\WeatherChart\WeatherChart\WeatherChart.csproj by default.

Here, we'll use the WeatherChart project in our .NET Core 3.0 project. Therefore, the WeatherChart project reference should be added to DotNetCore3FlexChart dependencies (right-click on Dependencies – Add Reference… - Projects - WeatherChart)

After that, open Project.cs from DotNetCore3FlexChart project and change the following line:

Application.Run(new Form1()); 

by 

Application.Run(new WeatherChart.Form1()); 

It means that the .NET Core 3.0 app (DotNetCore3FlexChart) will run WeatherChart.Form1 from WeatherChart assembly instead of own Form1\.

That’s all!

If you run the WeatherChart project it will be launched as .NET Framework 4.0 app.

But if you run the DotNetCore3FlexChart project then the WeatherChart assembly will be launched in .NET Core 3.0 environment.

.NET Core 3.0 Preview Caveats

Using the .NET Core 3.0 Preview for any kind of day-to-day work isn’t recommended at this point, as it’s obviously still work in progress. As the steps above illustrate, much of the project creation and migration processes require a lot of manual configuration from the user, and it’s possible to find some bugs and unfinished implementations presently.The lack of designer support also makes working with the preview somewhat difficult, though Microsoft has committed to adding this feature in the coming months.

Overall, .NET Core 3.0 will be an important change for developers, though this preview is merely the first step.



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