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 :: 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 = "catcher_hwq@outlook.com", 
                }, 
                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. 

 



European ASP.NET Core Hosting :: How to Create a Multi Tenant .NET Core Application

clock January 21, 2020 07:30 by author Scott

Introduction

In the final installment we will extend our multi-tenant solution to allow each tenant to have different ASP.NET Identity providers configured. This will allow each tenant to have different external identiy providers or different clients for the same identity provider.

This is important to allow consent screens on third party services reflect the branding of the particular tenant that the user is signing in to.

Tenant specific authentication features

In this post we will enable three features

Allow different tenants to configure different authentication options

This is useful if different tenants want to allow different ways of signing in, e.g. one tenant might want to allow Facebook and Instagram while another wants local logins only.

Make sure each tenant has their own authentication cookies

This is useful if tenants are sharing a domain, you don’t want the cookies of one tenant signing you in to all tenants.

Note: If you follow this post your tenants will be sharing decryption keys so one tenant’s cookie is a valid ticket on another tenant. Someone could send one tenant’s cookie to a second tenant, you will need to either also include a tenant Id claim or extend this further to have seperate keys to verify the cookie supplied is intended for the tenant.

Allow different tenants to use different configured clients on an external identity provider

With platforms such as Facebook if it’s the first time the user is signing in they will often be asked to grant access to the application for their account, it’s importannt that this grant access screen mentions the tenant that is requesting access. Otherwise the user might get confused and deny access if it’s from a shared app with a generic name.

Implementation

There are 3 main steps to our solution

1. Register the services depending on your tenant: Configure the authentication services depending on which tenant is in scope

2. Support dynamic registration of schemes: Move the scheme provider to be fetched at request time to reflect the current tenant context

3. Add an application builder extension: Make it nice for developers to enable the feature

This implementation is only compatible with ASP.NET Core 2.X. In 1.0 the Authentication was defined in the pipeline so you could use branching to configure services on a per-tenant basis, however this is no longer possible. The approach we’ve taken is to use our tenant specific container to register the different schemes/ options for each tenant.

This post on GitHub outlines all of the changes between 1.0 and 2.0.

1. Register the services depending on your tenant

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    ...

    return services.UseMultiTenantServiceProvider<Tenant>((t, c) =>
    {
        //Create a new service collection and register all services
        ServiceCollection tenantServices = new ServiceCollection();       

        var builder = tenantServices.AddAuthentication(o =>
            {
                //Support tenant specific schemes
                o.DefaultScheme = $"{t.Id}-{IdentityConstants.ApplicationScheme}";
            }).AddCookie($"{t.Id}-{IdentityConstants.ApplicationScheme}", o =>
            {
                ...
            });

        //Optionally add different handlers based on tenant
        if (t.FacebookEnabled)
                builder.AddFacebook(o => {
                    o.ClientId = t.FacebookClientId;
                    o.ClientSecret = t.FacebookSecret; });

        //Add services to the container
        c.Populate(tenantServices);

        ...
    });
}

Seems too easy right? It is. If you run it now your handlers aren’t registered using the default “.UseAuthentication” middleware. The schemes are registered in the middleware constructor before you have a valid tenant context. Since it doesn’t support registering schemes dynamically OOTB we will need to slightly modify it.

2. Update the authentication middleware to support dynamic registration of schemes

Disclaimer ahead! The ASP.NET framework was written by very smart people so I get super nervous about making any changes here - I’ve tried to limit the change but there could be unintended consequences! Proceed with caution

We’re going to take the existing middleware and just move the IAuthenticationSchemeProvider injection point from the constructor to the Invoke method. Since the invoke method is called after we’ve registered our tenant services it will have all the tenant specific authentication services available to it now.

/// <summary>
/// AuthenticationMiddleware.cs from framework with injection point moved
/// </summary>
public class TenantAuthMiddleware
{
    private readonly RequestDelegate _next;

    public TenantAuthMiddleware(RequestDelegate next)
    {
        _next = next ?? throw new ArgumentNullException(nameof(next));
    }  

    public async Task Invoke(HttpContext context, IAuthenticationSchemeProvider Schemes)
    {
        context.Features.Set<IAuthenticationFeature>(new AuthenticationFeature
        {
            OriginalPath = context.Request.Path,
            OriginalPathBase = context.Request.PathBase
        });

        // Give any IAuthenticationRequestHandler schemes a chance to handle the request
        var handlers = context.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
        foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync())
        {
            var handler = await handlers.GetHandlerAsync(context, scheme.Name)
                as IAuthenticationRequestHandler;
            if (handler != null && await handler.HandleRequestAsync())
            {
                return;
            }
        }

        var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync();
        if (defaultAuthenticate != null)
        {
            var result = await context.AuthenticateAsync(defaultAuthenticate.Name);
            if (result?.Principal != null)
            {
                context.User = result.Principal;
            }
        }       

        await _next(context);
    }
}

3. Add an application builder extension to register our slightly modified authentication middleware

This provides a nice way for the developer to quickly register the tenant aware authentication middleware

/// <summary>
/// Use the Teanant Auth to process the authentication handlers
/// </summary>
/// <param name="builder"></param>
/// <returns></returns>
public static IApplicationBuilder UseMultiTenantAuthentication(this IApplicationBuilder builder)
    => builder.UseMiddleware<TenantAuthMiddleware>();

Now we can register the tenant aware authenticaion middleware like this

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    ...

    app.UseMultiTenancy()
        .UseMultiTenantContainer()
        .UseMultiTenantAuthentication();
}

Wrapping up

In this post we looked at how we can upgrade ASP.NET Core to support tenant specifc authentication, this means each tenant can have different external identify providers registered and connect to different clients for each of those providers.



European ASP.NET Core Hosting :: JWT Token Authentication

clock December 17, 2019 11:29 by author Peter

In web applications, security is essential. Say that the user wants to use the resources of our system. For that, we need to authenticate the user. Authentication means need to check whether the user is eligible to use the system or not. Generally, we do authentication via username (in the form of a unique user name or email ID) and a password. If the user is authenticated successfully, then we allow that user to use the resources of our system. But what about subsequent requests? If the user has been already identified then s/he does not need to provide credentials each time. Once authenticated, for a particular period s/he can use the system's resources. In a traditional approach, we used to save Username in Session. This session period is configurable, which means the session is valid for about 15 or 20 minutes. This session is stored in server's memory. After expiration of the session, the user needs to login again.

But here, there are couple of problems.

  1. The session can be hijacked.
  2. If we have multiple instances of server with load balancer, then if the request goes to a server other than the server which has authenticated the earlier request, then it will invalidate that session. Because the session is not distributed among all the servers, we have to use a 'Sticky' session; that is we need to send each subsequent request to the same server only. Here, we can also store session in database instead of the server's memory. In that case, we need to query the database each time, and that's extra work which may increase the overall latency.

To solve this problem, we can do authentication via JWT i.e. JSON web token. After successful authentication, the server will generate a security token and send it back to the client. This token can be generated using a symmetric key algorithm or an asymmetric key algorithm. On each subsequent request after a successful login, the client will send a generated token back to the server. The server will check whether the sent token is valid or not and also checks whether its expired or not. The client will send this token in Authentication Bearer header.

JWT token has a particular format. Header, Payload, and Signature.

  1. Header
    - We need to specify which token system we want to use and also need to specify the algorithm type.
  2. Payload
    - This is a token body. Basically, it contains expiry detail, claims details, issuer detail, etc.
  3. Signature
    - To create the signature part we have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that.

E.g. HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

Benefits of using JWT

  1. JSON parser is common in programming languages.
  2. Secure. We can use a Symmetric or Asymmetric key algorithm.
  3. Less verbose in comparison to SAML.

I have created an ASP.Net Core web API sample application. JWTAuthService is responsible for the generation and validation of token. Feel free to download and contribute to the code on Github.



About HostForLIFE.eu

HostForLIFE.eu 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 2016 Hosting, ASP.NET Core 2.2.1 Hosting, ASP.NET MVC 6 Hosting and SQL 2017 Hosting.


Tag cloud

Sign in