European ASP.NET 4.5 Hosting BLOG

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

ASP.NET Core 5.0.2 Hosting - HostForLIFE :: Unit Testing Using XUnit And MOQ In ASP.NET Core

clock April 14, 2021 09:51 by author Peter

Writing unit tests can be difficult, time-consuming, and slow when you can't isolate the classes you want to test from the rest of the system. In this course, Mocking in .NET Core Unit Tests with Moq: Getting Started, you'll learn how to create mocks and use them as dependencies to the classes you want to test. First, you'll discover how to configure mocked methods and properties to return specific values. Next, you'll cover how to perform behavior/interaction testing. Finally, you'll explore how to set up mocked exceptions and events. When you're finished with this course, you'll have the necessary knowledge to use Moq to unit test your classes in isolation by creating and using mock objects.


Setup the Project
Let's create a sample web API Project with basic crud operations using EF Core code first approach.

Since .Net 5.0 installed on my machine so that I am going with the latest template we can choose what version we are comfortable with.

Create the Model Folder and inside will configure the Model class and DbContext for the EntityFramework Core Code First approach setup.


Employee.cs
    using System;  
    using System.Collections.Generic;  
    using System.ComponentModel.DataAnnotations;  
    using System.Linq;  
    using System.Threading.Tasks;  
      
    namespace UnitTest_Mock.Model  
    {  
        public class Employee  
        {  
            [Key]  
            public int Id { get; set; }  
            public string Name { get; set; }  
            public string Desgination { get; set; }  
        }  
    }  

 AppDbContext.cs
    using Microsoft.EntityFrameworkCore;  
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Threading.Tasks;  
      
    namespace UnitTest_Mock.Model  
    {  
        public partial class AppDbContext : DbContext  
        {  
            public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)  
            {  
      
            }  
            public DbSet<Employee> Employees { get; set; }  
        }  
    }  

Let's set up the connection string to perform the code first operations.

appsettings.json
    {  
      "Logging": {  
        "LogLevel": {  
          "Default": "Information",  
          "Microsoft": "Warning",  
          "Microsoft.Hosting.Lifetime": "Information"  
        }  
      },  
      "AllowedHosts": "*",  
      "ConnectionStrings": {  
        "myconn": "server=Your server name; database=UnitTest;Trusted_Connection=True;"  
      }  
    }  


 Startup.cs
    using Microsoft.AspNetCore.Builder;  
    using Microsoft.AspNetCore.Hosting;  
    using Microsoft.AspNetCore.HttpsPolicy;  
    using Microsoft.AspNetCore.Mvc;  
    using Microsoft.EntityFrameworkCore;  
    using Microsoft.Extensions.Configuration;  
    using Microsoft.Extensions.DependencyInjection;  
    using Microsoft.Extensions.Hosting;  
    using Microsoft.Extensions.Logging;  
    using Microsoft.OpenApi.Models;  
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Threading.Tasks;  
    using UnitTest_Mock.Model;  
    using UnitTest_Mock.Services;  
      
    namespace UnitTest_Mock  
    {  
        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.AddControllers();  
                services.AddSwaggerGen(c =>  
                {  
                    c.SwaggerDoc("v1", new OpenApiInfo { Title = "UnitTest_Mock", Version = "v1" });  
                });  
                #region Connection String  
                services.AddDbContext<AppDbContext>(item => item.UseSqlServer(Configuration.GetConnectionString("myconn")));  
                #endregion  
                services.AddScoped<IEmployeeService, EmployeeService>();  
            }  
      
            // 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();  
                    app.UseSwagger();  
                    app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "UnitTest_Mock v1"));  
                }  
      
                app.UseHttpsRedirection();  
      
                app.UseRouting();  
      
                app.UseAuthorization();  
      
                app.UseEndpoints(endpoints =>  
                {  
                    endpoints.MapControllers();  
                });  
            }  
        }  
    }  


Create the tables by using the below commands in the console.
 
Step 1
 
To create a migration script

    PM> Add-Migration 'Initial'  

Step 2
 
To execute the script in SQL Db

    PM> update-database  

Create a Services folder where we perform our business logic for all the operations.

EmployeeService.cs
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Threading.Tasks;  
    using UnitTest_Mock.Model;  
    using Microsoft.EntityFrameworkCore;  
      
    namespace UnitTest_Mock.Services  
    {  
        public class EmployeeService : IEmployeeService  
        {  
            #region Property  
            private readonly AppDbContext _appDbContext;  
            #endregion  
     
            #region Constructor  
            public EmployeeService(AppDbContext appDbContext)  
            {  
                _appDbContext = appDbContext;  
            }  
            #endregion  
      
            public async Task<string> GetEmployeebyId(int EmpID)  
            {  
                var name = await _appDbContext.Employees.Where(c=>c.Id == EmpID).Select(d=> d.Name).FirstOrDefaultAsync();  
                return name;  
            }  
      
            public async Task<Employee> GetEmployeeDetails(int EmpID)  
            {  
                var emp = await _appDbContext.Employees.FirstOrDefaultAsync(c => c.Id == EmpID);  
                return emp;  
            }  
        }  
    }  


IEmployeeService.cs
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Threading.Tasks;  
    using UnitTest_Mock.Model;  
      
    namespace UnitTest_Mock.Services  
    {  
       public interface IEmployeeService  
        {  
            Task<string> GetEmployeebyId(int EmpID);  
            Task<Employee> GetEmployeeDetails(int EmpID);  
        }  
    }  


Define these services in Startup. cs file which I have already highlighted in the above-mentioned startup.cs file.
 
Create API methods for those services in the controller class.
 
EmployeeController.cs
    using Microsoft.AspNetCore.Mvc;  
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Threading.Tasks;  
    using UnitTest_Mock.Model;  
    using UnitTest_Mock.Services;  
      
    namespace UnitTest_Mock.Controllers  
    {  
        [Route("api/[controller]")]  
        [ApiController]  
        public class EmployeeController : ControllerBase  
        {  
            #region Property  
            private readonly IEmployeeService _employeeService;  
            #endregion  
     
            #region Constructor  
            public EmployeeController(IEmployeeService employeeService)  
            {  
                _employeeService = employeeService;  
            }  
            #endregion  
      
            [HttpGet(nameof(GetEmployeeById))]  
            public async Task<string> GetEmployeeById(int EmpID)  
            {  
                var result = await _employeeService.GetEmployeebyId(EmpID);  
                return result;  
            }  
            [HttpGet(nameof(GetEmployeeDetails))]  
            public async Task<Employee> GetEmployeeDetails(int EmpID)  
            {  
                var result = await _employeeService.GetEmployeeDetails(EmpID);  
                return result;  
            }  
      
        }  
    }   


Let us create another testing project inside this solution project where we can write test cases for those functions
    Right-click on the Solution
    Click on Add - New project
    Search for X-Unit Test project.

Choose the target framework same as where we have used in our API project.

 

Install the Moq package inside this unit test project.


Create a class inside this Test project to define all our respective test cases but before that, we have to insert data into the table which we have created. Open the SQL Server and insert dummy data to the employee table.
 
EmployeeTest.cs
    using Moq;  
    using UnitTest_Mock.Controllers;  
    using UnitTest_Mock.Model;  
    using UnitTest_Mock.Services;  
    using Xunit;  
      
    namespace UnitTesting  
    {  
       public class EmployeeTest  
        {  
            #region Property  
            public Mock<IEmployeeService> mock = new Mock<IEmployeeService>();  
            #endregion  
      
            [Fact]  
            public async void GetEmployeebyId()  
            {  
                mock.Setup(p => p.GetEmployeebyId(1)).ReturnsAsync("JK");  
                EmployeeController emp = new EmployeeController(mock.Object);  
                string result = await emp.GetEmployeeById(1);  
                Assert.Equal("JK", result);  
            }  
            [Fact]  
            public async void GetEmployeeDetails()  
            {  
                var employeeDTO = new Employee()  
                {  
                    Id = 1,  
                    Name = "JK",  
                    Desgination = "SDE"  
                };  
                mock.Setup(p => p.GetEmployeeDetails(1)).ReturnsAsync(employeeDTO);  
                EmployeeController emp = new EmployeeController(mock.Object);  
                var result = await emp.GetEmployeeDetails(1);  
                Assert.True(employeeDTO.Equals(result));  
            }  
        }  
    }  


setting up the mock for our API business services under the controller level to check the result and compare with user-defined values.
 
we can debug the test cases to check the output in running mode.
 
Run all the test cases to verify whether they are passed or failed.
    Click on View in the Top left
    Click on Test explorer.

In the above image, we can see all our test cases are passed and their time duration as well. Hope this article helps you in understanding unit testing using the Mock object.



ASP.NET Core Hosting - HostForLIFE :: The Role Of Binding Class In .NET

clock April 5, 2021 06:58 by author Peter

The Binding class is used to bind a property of a control with the property of an object. For creating a Binding object, the developer must specify the property of the control, the data source, and the table field to which the given property will be bound.

Properties and Events of Binding class
BindingMemberInfo

This property retrieves an object that contain the current binding info, based on the dataMember parameter in the Binding constructor.

ControlUpdateMode
This property specifies or retrieves when data source changes are transferred to the bound control property.

IsBinding
This property retrieves a value that indicates whether the binding is active.

Format
This event occurs when the data value is bound to the property of a control.

The following source code demonstrate how to use the control property of the Binding class.

TextBox txtProductName=new TextBox();  
Label lblRecordNumber=new Label(‘);  
…………………………………………………………….  
SqlDataAdapter sqldaProducts=new SqlDataAdapter(“SELECT * FROM Products”,sqlconProducts);  
DataSet dsetProducts=new DataSet(“Products”);  
sqldaProducts.Fill(dsetProducts,”Products”);  
Binding bndProductName=new Binding(“Text”,dsetProducts,”Products.ProductName”);  
txtProductName.DataBindings.Add(bndProductName);  
MessageBox.Show(“ProductName field is bound to “ +bndProductName.Control.Name +”text box.”,”Message”);  
lblRecordNumber.Text=Convert.ToString(bndProductName.BindingManagerBasePosition + 1); 


In this source code, a TextBox and a Label control is created. This records from the Products table are fetched using the SqlDataAdapter and DataSet. An instance of the Binding class is created with three parameters. The ProductName column of the Products table is bound to the textbox. The message box is displayed stating that the product field is bound to txtProductName control. The label lblRecordNumber , displays the position of the record that is displayed using the BindingManagerBase property of the Binding object.


The source code demonstrate how to use the Format event of the Binding class.


TextBox  txtorderdate=new  TextBox();  
Binding bndOrderDate;  
………………………………….  
SqlDataAdapter sqldaOrders=new SqlDataAdapter(“SELECT * from Orders”,sqlconOrders);  
DataSet dsetOrders=new DataSet();  
sqldaOrders.Fill(dsetOrders,”Orders”);  
bndOrderDate=new Binding(“Text”,dsetOrders, “Orders.OrderDate”);  
bndOrderDate.Format+=new ConvertEventHandler(bndOrderDate_Format);  
txtOrderDate.DataBindings.Add(bndOrderDate);  
…………………………  
Private void bndOrderDate_Format(object sender, ConvertEventArgs e)  
{  
   e.Value=Convery.ToDateTime(e.Value).ToString(“MM/dd/YYY”);  
}  

In this source code, a Text Box control namely, txtOrderDate is created. The records from the Orders table are fetched using the SqlDataAdapter and DataSet . An instance of the Binding class is created with three parameters. The DataBindings property binds the Binding object to textbox. This binds the OrderDate column of the Orders table to textbox. The Format event is raised before the TextBox control displays the date value. This event formats the data in the MM/DD/YYYY format.

BindingSource Class

The BindingSource class is used to encapsulate a data source in a form. The properties of this class can be used to get the list to which the connector is bound.

Properties of BindingSource Class
AllowNew

Specifies or retrieves a value which indicates that the AddNew() method can be used to add items to the list.

Filter
Specifies or retrieves the expression used to filter rows which are viewed.

List
Retrieves the list to which the connector is bound.


RaiseListChangedEvents

Specifies or retrieves a value that indicates whether the ListChanged events should be raised.


Sort

Specifies or retrieves the name of columns used for sorting and sort order to view rows in the data source.

Methods of BindingSource Class
Find

Finds a particular item in the data source.

GetListName
Retrieves the name of list that supplies data for binding.

GetRelatedCurrencyManager
Retrieves the related currency manager for a particular data member.

IndexOf
Searches for an object and returns the index of its first occurrence in the list.

RemoveFilter
Removes the filter which is associated with the BindingSource.

ResetCurrentItem
Enables the control bound to BindingSource to re-read the currently selected item. It also refreshes the display value.

ResetItem
Enables the control bound to BindingSource to reread the item at the specified index, it also retrieves the display value.

 

The following source code creates a DataGridView control and displays the filtered records from the database.


BindingSource bndsrcCustomers;  
…………………….  
SqlDataAdapter sqldaCustomers=new SqlDataAdapter(“SELECT * from Customers”, sqlconCustomers);  
DataSet destCustomers=new DataSet();  
sqldaCustomers.Fill(dsetCustomers,”Customers”);  
bndsrcCustomers=new BindingSource(dsetCustomers, “Cutomers”);  
bndsrcCustomers.AllowNew=true;  
bndsrcCustomers.DataSource=dsetCustomers.Tables(“Customers”);  
bndsrcCustomers.Filter=”City=’Noida’ ”;  
Button btnShowAll=new Button();  
DataFridView dgvwCustomers=new DataGridView();  
dgvwCustomers.Size=new Size(600,300);  
dgvwCustomers.DataSource=bndsrcCustomers;  
Controls.Add(dgvwCustomers);  
………………..  
Private void btnShowAll_Click(object sender , EventArgs e)  
{  
   bndsrcCustomers.RemoveFilter();  
}  

In this source code , records from the Customers table are fetched using the SqlDataAdapter and DataSet. The BindingSource object is created to refer to the DataSet bound to the table. The AllowNew property is set to true, which invokes the AddNew() method to add items to the list. The DataSource property of the BindingSource object is set to the DataSet object. The Filter property retrieves the records, which contain the value Noida in the city column. The DataGridView Control is created and the DataSource property of this control is set to the BindingSource object. This displays the filtered records of the BindingSource object in a grid view. When the user clicks the ShowAll button, the RemoveFilter() method displays all the records from the table by removing the filter applied on them.

Events of BindingSource class

Event
Description
AddingNew
Occurs before an item is inserted to the list.
CurrentItemChanged
Occurs when the value of the Current property has been changed.
ListChanged
Occurs when the item or list in the list changes.
PositionChanged
Occurs when the value of the Position property has been changed.


BindingSource bndsrcCustomer;  
…………………………………  
SqlDataAdapter sqldaCustomers=new SqlDataAdapter(“SELECT * FROM Customers”,sqlconCustomers);  
DataSet dsetCustomers=new DataSet();  
saldaCustomers.Fill(dsetCustomers,”Customers”);  
bndsrcCustomers=new BindingSource(dsetCustomers, “Customers”);  
bndsrcCustomers.AllowNew=true;  
bndsrcCustomers.DataSource=dsetCustomers.Tables(“Customers”);  
txtCustomerID.DataBindings.Add(“Text”, bndsrcCustomer, “CustomerID”);  
txtContactName.DataBindings.Add(“Text”, bndsrcCustomer, “ContactName”);  
txtCity.DataBindings.Add(“Text”, bndsrcCustomer,”City”);  
bndsrcCustomer.PosititonChanged+=new EventHanlder(bndsrcCustomer_PositionChnaged);  
bndsrcCustomer.MoveLast();  
……………………………..  
private void bndsrcCustomer_PositionChanged(object sender,EventArgs e)  
{  
   txtPosition.Text =( bndsrcCustomer.Position+1).ToString();  
}  

This source records from Customers table are fetched using the SqlDataAdapter and DataSet. An object of the BindingSource class is created to refer to the DataSet bound to the table. The DataSource property of the BindingSource object is set to the DataSet object. The DataBindings property binds the BindingSource object to txtCustomerID, txtContactName, and txtCity to display the ID, name and city respectively. The PositionChanged event occurs when the index position of the current record is changed . This event displays the position of the record in the TextBox control, txtPostiton.

Sort Property of the BindingSource Class
The Sort property of the BindingSource class is used to sort rows in a table. The internal list supports sorting only if it implements the IBindingList or IBindingListView interfaces. The list will change depending on the interfaces being implemented.

Properties of IBindingList and IBindingListView Interfaces.
SortProperty

When the BindingSource object implements the IBindingList interface, this property is set. The property retrieves the PropertyDescriptor used for sorting the list. The PropertyDescriptor class provides information about the property used for sorting such as name, attributes, and the type.

SortDirection
When the BindingSource object implements the IBindingList interface, this property is set. This property retrieves the sorting order such as ascending or descending order. These values are defined in the ListSortDirection enumeration.

SortDescriptions
When the BindingSource object implements the IBindingListView interface, this property is set.
Source Code below uses the Sort property to sort the records of the table.

 

SqlDataAdapter  sqldaSuppliers=new SqlDataAdapter(“SELECT * from Suppliers”, sqlconSuppliers);  
DataSet dsetSuppliers=new DataSet();  
SqldaSuppliers.Fill(dsetSuppliers, “Suppliers”);  
BindingSource bndsrcSuppliers=new BindingSource(destSuppliers, “Suppliers”);  
bndsrcSuppliers.AllowNew=true;  
bndsrcSuppliers.DataSource=dsetSuppliers.Tables(“Suppliers”);  
bndsrcSuppliers.Sort=”City DESC”;  
DataGridView dgvwSuppliers=new DataGridView();  
dgvwSuppliers.Size=new Size(450,110);  
dgvwSuppliers.DataSource=bndsrcSuppliers;  
Controls.Add(dgvwSuppliers);  

This source code , records from the suppliers table are fetched using the SqlDataAdapter and DataSet. An object of the BindingSource class is created to refer to the DataSet bound to the table. The DataSource property of the BindingSource object is set to the DataSet object. The Sort property sorts the City column of the Suppliers table in descending order. The DataGridView control is created and the DataSource property of this control is set to the BindingSource object. This displays the records of the BindingSource object in a grid view.


ASP.NET Core Hosting - HostForLIFE :: How to Create Your First Application With ASP.NET Core 3.1?

clock March 29, 2021 07:11 by author Peter

In this article, we will create our first ASP.NET Core application with the Visual Studio 2019 and .NET Core 3.1 version. This article is part of the ASP.NET Core series that I am going to start. In this series of articles, I will try to cover the basics as well as will create a demo application for the learning purpose.

What is ASP.NET Core?
ASP.NET Core is a framework for building modern web applications and services. It is part of .NET Core which is a cross-platform as well as an open-source framework. We said cross platforms means, we can develop and deploy the web application targeting several operating systems including Windows, Linux as well as macOS. Another feature that makes it popular are mentioned below,

  • Cross-Platform as well as Open Source.
  • Built-in support for the dependency injection (DI).
  • It also includes a built-in Web server i.e. Kestral. You can run your application directly with the Kestral or can host your application under IIS, Ngnix, Apache, etc.
  • Unified programming model for building the web as well as Web API (with the use of Controller as the base class).
  • Lightweight and high-performance modular request pipeline which is suitable for the modern cloud-based application.

For creating our first ASP.NET Core application, I am using Visual Studio 2019 with .NET core 3.1 Version.

Let’s Begin,

Open Visual Studio 2019 and click on Create a new project

On the next screen, select ASP.NET Core Web Application and click on the Next button

Configure your project name and the location where you want to create the application. Click on create button.


As It’s our first application, we are trying to make it as simple as possible. Select .Net Core and ASP.NET Core 3.1 Version (as I am going to use the same version in upcoming tutorials of this series). Select the Empty template (We can create ASP.NET Core API, ASP.NET Core Application with Razor Pages, ASP.NET Core MVC, etc. application with the ASP.NET .NET Core). Unselect the configure for HTTPS checkbox as we are trying to make it as simple as possible and SSL is not required for that. Click on create button.

Once the application is created you will see a screen like below.

Go to top navigation controls and run the Application on IIS Express as shown in the below image.

On clicking on IIS Express, You will see that the application is launched in the browser with a text as Hello World on the screen.

Now you might be confused about where this “Hello World” text is coming from. In order to understand that let’s open the startup.cs file from solution explorer. I have highlighted the line in the Configure method (Configure method is called during the runtime and used to configure the HTTP request pipeline. We will see more in detail about it when we cover Middleware use in ASP.NET Core web application)

Let’s change that text to something that you want to see on screen. For demonstration, I am changing it to “Hello World from IT Tutorials with Example”.

 
Build and run the application as we did in the above steps. The text which we changed is shown on the web browser.

Great! We have created our First Hello World Application with ASP.NET Core. In the next article, we will understand the basic file structure of the project that we have created. I hope you like it. Thanks.

 

 



ASP.NET Core 5.0.2 Hosting - HostForLIFE :: Upload And Download Multiple Files Using Web API

clock March 23, 2021 06:54 by author Peter

Today, we are going to cover uploading & downloading multiple files using ASP.Net Core 5.0 web API by a simple process.

 
Note
Since I have the latest .Net 5.0 installed on my machine I used this. This same technique works in .Net Core 3.1 and .Net Core 2.1 as well.
 
Begin with creating an empty web API project in visual studio and for target framework choose .Net 5.0.
 
No external packages were used in this project.
 
Create a Services folder and inside that create one FileService class and IFileService Interface in it.
 
We have used three methods in this FileService.cs

    UploadFile
    DownloadFile
    SizeConverter

Since we need a folder to store these uploading files, here we have added one more parameter to pass the folder name as a string where it will store all these files.
 
FileService.cs
    using Microsoft.AspNetCore.Hosting;  
    using Microsoft.AspNetCore.Http;  
    using System;  
    using System.Collections.Generic;  
    using System.IO;  
    using System.IO.Compression;  
    using System.Linq;  
    using System.Threading.Tasks;  
      
    namespace UploadandDownloadFiles.Services  
    {  
        public class FileService :IFileService  
        {  
            #region Property  
            private IHostingEnvironment _hostingEnvironment;  
            #endregion  
     
            #region Constructor  
            public FileService(IHostingEnvironment hostingEnvironment)  
            {  
                _hostingEnvironment = hostingEnvironment;  
            }  
            #endregion  
     
            #region Upload File  
            public void UploadFile(List<IFormFile> files, string subDirectory)  
            {  
                subDirectory = subDirectory ?? string.Empty;  
                var target = Path.Combine(_hostingEnvironment.ContentRootPath, subDirectory);  
      
                Directory.CreateDirectory(target);  
      
                files.ForEach(async file =>  
                {  
                    if (file.Length <= 0) return;  
                    var filePath = Path.Combine(target, file.FileName);  
                    using (var stream = new FileStream(filePath, FileMode.Create))  
                    {  
                        await file.CopyToAsync(stream);  
                    }  
                });  
            }  
            #endregion  
     
            #region Download File  
            public (string fileType, byte[] archiveData, string archiveName) DownloadFiles(string subDirectory)  
            {  
                var zipName = $"archive-{DateTime.Now.ToString("yyyy_MM_dd-HH_mm_ss")}.zip";  
      
                var files = Directory.GetFiles(Path.Combine(_hostingEnvironment.ContentRootPath, subDirectory)).ToList();  
      
                using (var memoryStream = new MemoryStream())  
                {  
                    using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))  
                    {  
                        files.ForEach(file =>  
                        {  
                            var theFile = archive.CreateEntry(file);  
                            using (var streamWriter = new StreamWriter(theFile.Open()))  
                            {  
                                streamWriter.Write(File.ReadAllText(file));  
                            }  
      
                        });  
                    }  
      
                    return ("application/zip", memoryStream.ToArray(), zipName);  
                }  
      
            }  
            #endregion  
     
            #region Size Converter  
            public string SizeConverter(long bytes)  
            {  
                var fileSize = new decimal(bytes);  
                var kilobyte = new decimal(1024);  
                var megabyte = new decimal(1024 * 1024);  
                var gigabyte = new decimal(1024 * 1024 * 1024);  
      
                switch (fileSize)  
                {  
                    case var _ when fileSize < kilobyte:  
                        return $"Less then 1KB";  
                    case var _ when fileSize < megabyte:  
                        return $"{Math.Round(fileSize / kilobyte, 0, MidpointRounding.AwayFromZero):##,###.##}KB";  
                    case var _ when fileSize < gigabyte:  
                        return $"{Math.Round(fileSize / megabyte, 2, MidpointRounding.AwayFromZero):##,###.##}MB";  
                    case var _ when fileSize >= gigabyte:  
                        return $"{Math.Round(fileSize / gigabyte, 2, MidpointRounding.AwayFromZero):##,###.##}GB";  
                    default:  
                        return "n/a";  
                }  
            }  
            #endregion  
      
        }  
    }  


SizeConverter function is used to get the actual size of our uploading files to the server.
 
IFileService.cs
    using Microsoft.AspNetCore.Http;  
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Threading.Tasks;  
      
    namespace UploadandDownloadFiles.Services  
    {  
       public interface IFileService  
        {  
            void UploadFile(List<IFormFile> files, string subDirectory);  
            (string fileType, byte[] archiveData, string archiveName) DownloadFiles(string subDirectory);  
             string SizeConverter(long bytes);  
        }  
    }  


Let's add this service dependency in a startup.cs file
 
Startup.cs
    using Microsoft.AspNetCore.Builder;  
    using Microsoft.AspNetCore.Hosting;  
    using Microsoft.AspNetCore.HttpsPolicy;  
    using Microsoft.AspNetCore.Mvc;  
    using Microsoft.Extensions.Configuration;  
    using Microsoft.Extensions.DependencyInjection;  
    using Microsoft.Extensions.Hosting;  
    using Microsoft.Extensions.Logging;  
    using Microsoft.OpenApi.Models;  
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Threading.Tasks;  
    using UploadandDownloadFiles.Services;  
      
    namespace UploadandDownloadFiles  
    {  
        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.AddControllers();  
                services.AddSwaggerGen(c =>  
                {  
                    c.SwaggerDoc("v1", new OpenApiInfo { Title = "UploadandDownloadFiles", Version = "v1" });  
                });  
      
                services.AddTransient<IFileService, FileService>();  
            }  
      
            // 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();  
                    app.UseSwagger();  
                    app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "UploadandDownloadFiles v1"));  
                }  
      
                app.UseHttpsRedirection();  
      
                app.UseRouting();  
      
                app.UseAuthorization();  
      
                app.UseEndpoints(endpoints =>  
                {  
                    endpoints.MapControllers();  
                });  
            }  
        }  
    }  

Create a FileController & now inject this IFileService using Constructor injection inside this FileController.
 
FileController.cs
    using Microsoft.AspNetCore.Hosting;  
    using Microsoft.AspNetCore.Http;  
    using Microsoft.AspNetCore.Mvc;  
    using System;  
    using System.Collections.Generic;  
    using System.ComponentModel.DataAnnotations;  
    using System.IO;  
    using System.Linq;  
    using System.Threading.Tasks;  
    using UploadandDownloadFiles.Services;  
      
    namespace UploadandDownloadFiles.Controllers  
    {  
        [Route("api/[controller]")]  
        [ApiController]  
        public class FileController : ControllerBase  
        {  
            #region Property  
            private readonly IFileService _fileService;  
            #endregion  
     
            #region Constructor  
            public FileController(IFileService fileService)  
            {  
                _fileService = fileService;  
            }  
            #endregion  
     
            #region Upload  
            [HttpPost(nameof(Upload))]  
            public IActionResult Upload([Required] List<IFormFile> formFiles, [Required] string subDirectory)  
            {  
                try  
                {  
                    _fileService.UploadFile(formFiles, subDirectory);  
      
                    return Ok(new { formFiles.Count, Size = _fileService.SizeConverter(formFiles.Sum(f => f.Length)) });  
                }  
                catch (Exception ex)  
                {  
                    return BadRequest(ex.Message);  
                }  
            }  
            #endregion  
     
            #region Download File  
            [HttpGet(nameof(Download))]  
            public IActionResult Download([Required]string subDirectory)  
            {  
      
                try  
                {  
                    var (fileType, archiveData, archiveName) = _fileService.DownloadFiles(subDirectory);  
      
                    return File(archiveData, fileType, archiveName);  
                }  
                catch (Exception ex)  
                {  
                    return BadRequest(ex.Message);  
                }  
      
            }  
            #endregion  
        }  
    }  

We can test our API's in both swagger and postman.

 
Here we see our two API's which we have created to upload and download, so let's test each of these individually.

 
Pass the folder name inside the subDirectory and add files below to save inside the server and under the folder name. In response we see the total count of our files and the actual size of our entire files.

 
Now will check with Download API. Since we have multiple files inside of our folder it will download as a Zip file where we need to extract that to check the files.



ASP.NET Core 5.0.2 Hosting - HostForLIFE :: How to Load 5 Million Records from CSV and Process Them In Under Three Seconds?

clock March 15, 2021 06:54 by author Peter

We have a scenario where we have to load 5 million records under 2 seconds from a CSV file using C#, then process it and return some processed records based on certain criteria too. This sounds like loading and processing may take more time but only if we do it in the wrong way.

This is what we will solve in the below code.
 
Let's dive in and do some processing ourselves. First download a file from the URL below, it is a sample Sales records CSV file with 5 million records.
http://eforexcel.com/wp/wp-content/uploads/2020/09/5m-Sales-Records.7z
 
Now we will do is load this CSV in our program and get the top ten sales records with maximum revenue in order.
    Stopwatch stopwatch = new Stopwatch();  
    stopwatch.Start();  
    //LOAD    
    //Created a temporary dataset to hold the records    
    List < Tuple < string, string, string >> listA = new List < Tuple < string, string, string >> ();  
    using(var reader = new StreamReader(@ "C:\Users\Lenovo\Desktop\5m Sales Records.csv")) {  
        while (!reader.EndOfStream) {  
            var line = reader.ReadLine();  
            var values = line.Split(',');  
            listA.Add(new Tuple < string, string, string > (values[0], values[1], values[11]));  
        }  
    }  
    //PROCESS    
    var top10HigestRevenueSalesRecords = from salesrec in listA.Skip(0).Take(10)  
    orderby salesrec.Item3  
    select salesrec;  
    //PRINT    
    foreach(var item in top10HigestRevenueSalesRecords) {  
        Console.WriteLine($ "{item.Item1} - {item.Item2} - {item.Item3}");  
    }  
    stopwatch.Stop();  
    Console.WriteLine($ "Time ellapsed {stopwatch.ElapsedMilliseconds/1000}");  
    Console.ReadLine();   

Now all three main steps in the process Load, Process, and Print were done in under 2 seconds.
 
Adding Parallel. For or Foreach does not either work much for this scenario, in fact, it will slow it down a bit with again a difference in nanoseconds which is not to be considered much.
 
We can improve it futher down to one second by using some custom Nuget packages  that decrease the downtime of loading large csv files.
    using LumenWorks.Framework.IO.Csv;  
    using(CsvReader csv = new CsvReader(new StreamReader(@ "C:\Users\Lenovo\Desktop\5m Sales Records.csv"), true)) {  
        while (csv.ReadNextRecord()) {  
            listA.Add(new Tuple < string, string, string > (csv[0], csv[1], csv[11]));  
        }  
    }   


Happy coding fellows.



ASP.NET Core 5.0.2 Hosting - HostForLIFE :: How To Use Postman With ASP.NET Core Web API Testing?

clock March 8, 2021 06:12 by author Peter

Manual Testing with Postman

If you are a developer, tester, or a manager, sometimes understanding various methods of API can be a challenge when building and consuming the application.

Generating good documentation and help pages for your Web API using Postman with .NET Core is as easy as making some HTTP calls.

Let’s start downloading simple To-do projects from GitHub.
Download and run the below TodoMvcSolution

Download Postman

Postman is a Google Chrome application for testing API calls. You can download and install Postman from below web site.

Here are the APIs we can test -  Get, Post, Put and Delete for this application.


Here are the Web APIs we want to test.
    //Copyright 2017 (c) SmartIT. All rights reserved.  
    //By John Kocer  
    // This file is for Swagger test, this application does not use this file  
    using System.Collections.Generic;  
    using Microsoft.AspNetCore.Mvc;  
    using SmartIT.Employee.MockDB;   
      
    namespace TodoAngular.Ui.Controllers  
    {  
      [Produces("application/json")]  
      [Route("api/Todo")]  
      public class TodoApiController : Controller  
      {  
        TodoRepository _todoRepository = new TodoRepository();  
      
        [Route("~/api/GetAllTodos")]  
        [HttpGet]  
        public IEnumerable<SmartIT.Employee.MockDB.Todo> GetAllTodos()  
        {  
          return _todoRepository.GetAll();  
        }  
      
        [Route("~/api/AddTodo")]  
        [HttpPost]  
        public SmartIT.Employee.MockDB.Todo AddTodo([FromBody]SmartIT.Employee.MockDB.Todo item)  
        {  
          return _todoRepository.Add(item);  
        }  
      
        [Route("~/api/UpdateTodo")]  
        [HttpPut]  
        public SmartIT.Employee.MockDB.Todo UpdateTodo([FromBody]SmartIT.Employee.MockDB.Todo item)  
        {  
          return  _todoRepository.Update(item);  
        }  
      
        [Route("~/api/DeleteTodo/{id}")]  
        [HttpDelete]  
        public void Delete(int id)  
        {  
          var findTodo = _todoRepository.FindById(id);  
          if (findTodo != null)  
            _todoRepository.Delete(findTodo);  
        }  
      }  
    }

Note - Your local port number may be different than mine. Use your local port number.
 
http://localhost:63274/api/GetAllTodos // GET
http://localhost:63274/api/AddTodo //POST
http://localhost:63274/api/UpdateTodo //PUT
http://localhost:63274/api/DeleteTodo/5 // DELETE
 
Testing GET with Postman
    Testing GET is very easy. First, we need to set HTTP Action from the drop-down list as GET.
    Then, we need to type or paste into the API URL box.
    Then, click the blue SEND button.

If the GET is successful, we see the status: 200 OK.

Testing POST with Postman
    First, we need to set Http Action from the dropdown list as POST.
    Then, we need to type or paste into the API URL box.
    AddTodo API accepts a Todo object in JSON format. We need to pass a new Todo JSON data.
    To pass JSON data we need to Select Body Tap.
    Select the Raw
    Select JSON(Application/JSON) as text format.
    Write or paste your Todo JSON data.
    Then, click the blue SEND button.

If the POST is successful, we see the status: 200 OK.
 
You will see Status:200 for success and the return value in the Return Body tab. We sent Publish Postman Todo item with id=0 and we received id=5 as result.

Testing PUT with Postman

    First, we need to set HTTP Action from the dropdown list as PUT.
    Then, we need to type or paste into the API URL.
    UpdateTodo API accepts a Todo object in JSON format. We need to pass an existing Todo JSON data.
    To pass JSON data we need to Select Body Tab
    Select the Raw format
    Select JSON(Application/JSON) as text format.
    Write or paste your Todo JSON
    Then click the blue SEND

If the PUT is successful, we see the status: 200 OK.

 
 
You will see Status:200 for success and the return value in the Return Body Tab. We sent Publish Postman Todo item with "name": "Publish Postman-In progress" and we receive an updated todo result.


Testing DELETE with Postman

    First, we need to set Http Action from the dropdown list as DELETE.
    Then, we need to type or paste into the API URL box.
    DeleteTodo/5 API accepts an id on the  We need to pass an existing Todo with an Id value.
    Then, click the blue SEND button.

If the Delete is successful, we see the status: 200 OK.

HostForLIFE ASP.NET Core 5.0.2 Hosting
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 customers from around the globe, spread across every continent. We serve the hosting needs of the business and professional, government and nonprofit, entertainment and personal use market segments.

 

 



ASP.NET Core 5.0.2 Hosting - HostForLIFE :: How To Implement Database Views Using Entity Framework (EF) Code First Approach?

clock March 1, 2021 06:32 by author Peter

There are several situations where your applications may need to display data by combining two or more tables, sometimes even more than 7-8 tables. In such a scenario, using Entity framework may result in a slow performance because we need to process by selecting data from a table, then run some loops from other tables.

However, the database itself has many features to handle the performance in these cases, such as stored procedures or creating views that are most recommended and result in better performance.
 
On the other hand, entity framework, open source ORM framework, is gaining huge popularity among the .net developer because of numerous advantages and speedup the coding as well as quite handy to control database directly form code.
 
In this article, I will show how to how to take the advantages of database views in entity framework and overcome the problems of complex joining/query by creating a view and handling those views in Entity framework.
 
Database view

A view is considered as a virtual table which is formed based on SQL statement of other tables. This can be considered as a real table; however, we cannot do commands like delete or update. In simple terms, it contains query to pull data from table(s). We generally use WHERE, FUNCTION and/or JOIN to tables to form a view.
 
We create views for query simplicity: we can write complex queries to select data from various tables and instead of writing those complex queries each time; we create views to use it like simple tables. Other advantages are performance improvements, data security and ease of use.
 
We can create view two ways (MS SQL server): SQL Script and Query Designer.
 
SQL Script Syntax
    CREATE VIEW view_name AS    
    SELECT column1, column2.....    
    FROM table_name    
    WHERE [condition];     

We can write complex queries using where, function, join etc. or you can even do union.
 
Query Designer
We can take advantages of query designer as shown,


We can add tables, add relations (auto relations based primarykey-foreignkey), modify alias as depicted in above diagram. There is option to modify query manually and check the results.
 
Handling Views in Entity Framework
We can utilize views in entity framework database first approach easily considering a model. However, in entity framework code first approach, we need to do tricks. If we create models of views then it will create tables of those views in add-migration and database update command.
 
Tricks
We can handle views in entity framework in two ways.
 
Option 1
Create a view combining multiple tables in the database manually and subsequently add an entity for the view. Finally, we can add ignore for the entity OnmodelCreating Entity builder, as shown below.
 
Sample Code
    protected override void OnModelCreating(ModelBuilder modelBuilder)    
    {    
      if (IsMigration)    
        modelBuilder.Ignore<ViewEntityName>();    
     ...    
    }   

With above trick, we can simply take advantages of entity model and ignore in migrations and database update in code first approach.
 
Option 2
Alternatively, you can create an extension or property for handling views in the database. In this option, we can create a view manually in the database then add an extension or property.
 
Sample Code
    //Property    
    class DBContext    
    {    
        public IQueryable<YourView> YourView     
        {    
            get    
            {    
                return this.Database.SqlQuery<YourView>("select * from dbo.ViewName");    
            }    
        }    
    }   


Extension
    static class DbContextExtensions    
    {    
        public static IQueryable<ViewNameModel>(this DbContext context)    
        {    
            return context.Database.SqlQuery<ViewNameModel>("select * from dbo.ViewName");    
        }    
    }  

We can build database context extension to handle view and use it in our solution with code first approach.
 
There are some other alternative methods as well, however, I prefer these options, as they are easy to implement.
 
Conclusion
In this article, we have learned how to implement database views in entity framework in code first approach and take advantages of those views to handle complex queries and overcome the problem of complex joining/query in entity framework. Database views is quite effective for complex queries in terms of performance, ease of use, data security and most importantly query simplicity.


HostForLIFE ASP.NET Core 5.0.2 Hosting
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 customers from around the globe, spread across every continent. We serve the hosting needs of the business and professional, government and nonprofit, entertainment and personal use market segments.



ASP.NET Core 5.0.2 Hosting - HostForLIFE :: How To Encrypt an AppSettings Key In Web.config?

clock February 22, 2021 06:20 by author Peter

Sometimes we come across a scenario where we need to encrypt a sensitive key in appSettings section in Web.config file. This blog demonstrates the  steps to encrypt a key and read the respective key in an ASP.NET application.

I have an appsettings key that is being called from .NET application. Before we are encrypting appsettings key in web.config.


Step 1 - Adding a section in configSections in web.config
    <configSections>
    <section name="secureAppSettings" type="System.Configuration.NameValueSectionHandler, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
    </configSections


Step 2 - Add secureAppSettings section under configuration
    <secureAppSettings>
    <add key="Password" value="XXXXXXXX"/>
    </secureAppSettings>

How To Encrypt a AppSettings Key In Web.config
Step 3 - Execute command from command prompt to encrypt secureAppSettings section
Open command prompt and execute the below commands.

cd C:\Windows\Microsoft.NET\Framework\v4.0.30319
aspnet_regiis.exe -pef "secureAppSettings" "your application web config path" -prov "DataProtectionConfigurationProvider"

After execution of the above command, secure app settings section encrypted as below.


Step 4 - Accessing appsettings key from .NET code
To access the encrypted key value in code, we can write it like below.
    using System.Collections.Specialized;

    var passwordValue = "";
    var section = System.Web.Configuration.WebConfigurationManager.GetSection("secureAppSettings") as NameValueCollection;
    if (section != null && section["Password"] != null)
    {
    passwordValue = section["Password"];
    }

Excellent! We successfully encrypted to a key in appsettings in web.config. Similarly, we can do the same steps while deploying a Web application to IIS.

HostForLIFE ASP.NET 3.1.9 Hosting
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 customers from around the globe, spread across every continent. We serve the hosting needs of the business and professional, government and nonprofit, entertainment and personal use market segments.



ASP.NET Core 3.1.9 Hosting - HostForLIFE :: Handling Larger JSON String Values In .NET And Avoiding Exceptions

clock February 16, 2021 06:49 by author Peter

Working with JSON within Web Services recently has become the latest and greatest simply because it plays so nicely with others and can often be very easily serialized and deserialized to fit your needs.
 
There is just something rewarding about having a massive collection of complex objects that can be thrown into a simple string and passed across however you see fit and then completely regenerated in its original collection in just a handful of code.
 
However sometimes these strings can get big and I mean really big, like exceeding default values big, and when this happens, exceptions happen. This post will cover a few ways that you can prevent a nasty InvalidOperationException that may look something like this with ease:
 

 
The Problem
You decide that paging data is for losers and decide to pull a graph of all of the data within your database, which will hypothetically contain thousands of complex objects, each with additional properties of their own. If your dataset is large enough, you’ll find yourself quickly exceeding the bounds that your Serializer can handle and you’ll be met with an exception and no data.
 
The Solution
There are three basic methods of handling this depending on your current environment:

    Setting the MaxJsonLength property default value within your web.config. (This will only apply to web-services that handle JSON).
     
    Setting the MaxJsonLength property of a JavascriptSerializer object to perform your serialization.
     
    If you are using MVC4 to handle returning your JSON values, you may want to override the default JsonResult() ActionResult and change the maximum size manually.
     
    Either of these changes will help you avoid any bumps in the road when passing across your large JSON values.

Option I: The MaxJsonLength Property for handling JSON in Web Services
The MaxJsonLength property which can be set within the web.config of your application controls the maximum size of the JSON strings that are accepted by the JsonSerializerclass. The default value is 102400 characters.
 
In order to increase the size of this value – you can just add the following code to your web.config file and set it to the value that you desire:

    <configuration>    
       <system.web.extensions>  
           <scripting>  
               <webServices>  
                   <!-- Update this value to change the value to   
                        a larger value that can accommodate your JSON   
                        strings -->  
                   <jsonSerialization maxJsonLength="86753090" />  
               </webServices>  
           </scripting>  
       </system.web.extensions>  
    </configuration>    


It is important to know that this setting within the web.config will only apply to actual Web Services that handle your JSON strings using the internal JsonSerializer. If you are still encountering issues after applying this change, you will likely want to continue reading and consider using an instance of the JsonSerializer class to handle setting this value.
 
Option II: Using the JavaScriptSerialzier and the MaxJsonLength Property to Handle Serializing JSON Values
Using an instance of a JavascriptSerializer will not actually inherit the previously defined within the web.config (as the web.config only applies to Web Services that handle the JSON) so you can easily just create an instance of the serializer and set the property accordingly:
    // Creates an instance of your JavaScriptSerializer   
    // and Setting the MaxJsonLength  
    var serializer = new JavaScriptSerializer() { MaxJsonLength = 86753090 };  
      
    // Perform your serialization  
    serializer.Serialize("Your JSON Contents");   


This will allow you to easily your larger data and adjust your maximum size easily.
 
Option III: Overriding the MVC4 JsonResult Action Result to Handle the Maximum Size
Much like the previous examples, every time that you are going to return a JsonResultyou can simply add the MaxJsonLength property to a specific value depending on the context of your specific action:
    return new JsonResult() {   
       Data = "Your Data",   
       MaxJsonLength = 86753090   
    };  


Or using the Json() method:
    JsonResult result = Json("Your Data");   
    result.MaxJsonLength = 8675309;   


However, if you want a more widespread solution that you could use within a single area of your application, you may want to consider overriding the JsonResult class and set your value within this newer class:

    // This ActionResult will override the existing JsonResult   
    // and will automatically set the maximum JSON length  
    protected override JsonResult Json(object data, string contentType, System.Text.Encoding contentEncoding, JsonRequestBehavior behavior)    
    {  
        return new JsonResult()  
        {  
            Data = data,  
            ContentType = contentType,  
            ContentEncoding = contentEncoding,  
            JsonRequestBehavior = behavior,  
            MaxJsonLength = Int32.MaxValue // Use this value to set your maximum size for all of your Requests  
        };  
    }  

From a JSON to a JMAN
Those are just a few methods that you should be able to use if you ever encounter an issue when passing larger JSON strings across your Controllers or through the use of Web Services. I am sure that there are likely several other ways to handle these same problems, but hopefully one of these will help you out if you are in a tight spot.

HostForLIFE ASP.NET 3.1.9 Hosting
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 customers from around the globe, spread across every continent. We serve the hosting needs of the business and professional, government and nonprofit, entertainment and personal use market segments.

 

 



ASP.NET Core 3.1.9 Hosting - HostForLIFE :: Unable To Resolve Service For Type ‘Swashbuckle.AspNetCore.Swagger.ISw

clock February 3, 2021 08:48 by author Peter

Recently, one of my team members faced this error while implementing Swagger in ASP.NET core.

Environment Details

  • Visual Studio 2019
  • ASP.NET Core 3.1
  • Swashbuckle.AspNetCore 5.6.3

Error
Unable to resolve service for type ‘Swashbuckle.AspNetCore.Swagger.ISwaggerProvider’ while attempting to Invoke middleware ‘Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware
 
The issue was with the Swagger generator. The swagger generator was not called or registered in container services of the startup file.
 
Below code: (startup.cs file) add services.AddSwaggerGen(),
    // This method gets called by the runtime. Use this method to add services to the container.  
    public void ConfigureServices(IServiceCollection services)  
    {  
        //...other methods added to servces  
        //...  
        //...  
      
        // Register the Swagger generator, defining 1 or more Swagger documents  
        services.AddSwaggerGen();  
      
        //....other methods added to servces  
        //...  
    }  


Additionally, you can modify the information displayed in swagger UI with the following code:
    // Register the Swagger generator, defining 1 or more Swagger documents  
    services.AddSwaggerGen(c =>  
    {  
        c.SwaggerDoc("v1", new OpenApiInfo  
        {  
            Version = "v1",  
            Title = "My Peter API",  
            Description = "Peter ASP.NET Core Web API",  
            TermsOfService = new Uri("https://Peter.com/terms"),  
            Contact = new OpenApiContact  
            {  
                Name = "Rijwan Ansari",  
                Email = string.Empty,  
                Url = new Uri("https://Peter.com/spboyer"),  
            },  
            License = new OpenApiLicense  
            {  
                Name = "Use under Open Source",  
                Url = new Uri("https://Peter.com/license"),  
            }  
        });  
    });  

This modification resolved the issue/error.

HostForLIFE ASP.NET 3.1.9 Hosting
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 customers from around the globe, spread across every continent. We serve the hosting needs of the business and professional, government and nonprofit, entertainment and personal use market segments.

 



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