European ASP.NET MVC Hosting

BLOG about Latest ASP.NET MVC Hosting and Its Technology - Dedicated to European Windows Hosting Customer

ASP.NET MVC Hosting - HostForLIFEASP.NET :: Partial View in MVC

clock December 13, 2022 07:32 by author Peter

Partial view in ASP.NET MVC is special view which renders a portion of view content. It is just like a user control of a web form application. Partial can be reusable in multiple views. It helps us to reduce code duplication. In other word a partial view enables us to render a view within the parent view.

The partial view is instantiated with its own copy of a ViewDataDictionary object which is available with the parent view so that partial view can access the data of the parent view. If we made the change in this data (ViewDataDictionary object), the parent view's data is not affected. Generally the Partial rendering method of the view is used when related data that we want to render in a partial view is part of our model.
 
Creating Partial View

To create a partial view, right-click on view -> shared folder and select Add -> View option. In this way we can add a partial view.


It is not mandatory to create a partial view in a shared folder but a partial view is mostly used as a reusable component, it is a good practice to put it in the "shared" folder.

HTML helper has two methods for rendering the partial view: Partial and RenderPartial.
    <div> 
        @Html.Partial("PartialViewExample") 
    </div> 
    <div> 
        @{ 
            Html.RenderPartial("PartialViewExample"); 
        } 
    </div>


@Html.RenderPartial
The result of the RenderPartial method is written directly into the HTTP response, it means that this method used the same TextWriter object as used by the current view. This method returns nothing.
 
@Html.Partial
This method renders the view as an HTML-encoded string. We can store the method result in a string variable.
The Html.RenderPartial method writes output directly to the HTTP response stream so it is slightly faster than the Html.Partial method.
Returning a Partial view from the Controller's Action method:
    public ActionResult PartialViewExample() 
    { 
        return PartialView(); 
    }


Render Partial View Using jQuery
Sometimes we need to load a partial view within a model popup at runtime, in this case we can render the partial view using JQuery element's load method.
    <script type="text/jscript"> 
            $('#partialView').load('/shared/PartialViewExample’); 
    </script> 

View Vs Partial View

View Partial View
View contains the layout page Partial view does not contain the layout page
_viewstart page is rendered before any view is rendered Partial view does not check for a _viewstart.cshtml. We cannot place any common code for a partial view within the _viewStart.cshtml page.
View may have markup tags like html, body, head, title, meta etc. The Partial view is specially designed to render within the view and as a result it does not contain any mark up.
Partial view is more lightweight than the view. We can also pass a regular view to the RenderPartial method.
If there is no layout page specified in the view, it can be considered as a partial view. In razor, there is no distinction between views and partial views as in the ASPX view engine (aspx and ascx).

 

 



ASP.NET MVC Hosting - HostForLIFEASP.NET :: CRUD Operation With Dapper Using ASP.NET Core 6 MVC

clock December 6, 2022 08:03 by author Peter

In this article will learn CURD (Create, Update, Read and Delete) operation which is common for most web applications. Here will understand SQL Database, Dapper Micro-ORM (Object Relation Mapper) along with repository pattern using ASP.NET Core 6 MVC.


What is Dapper?
Dapper is a micro ORM or it is a simple object mapper framework that helps to map the native query output to a domain class.
Creating a New Project in Visual Studio 2022

Start Visual Studio software and select Create a new project.

In the Create a new project dialog, select ASP.NET Core Web App (Model-View Controller) > Next.

In the Create a new project dialog, select ASP.NET Core Web App (Model-View Controller) > Next.

In the Configure your new project dialog, enter CURDWithDapperCore6MVC_Demo for Project name. It's important to name the project CURDWithDapperCore6MVC_Demo. The capitalization needs to match each namespace when code is copied. Select Next.

In the Additional information dialog, select .NET 6.0 (Long-term support). Select Create

The Visual Studio project 2022 will now generate the structure for the selected application. In this example, we are using ASP.Net MVC so we can create a controller to write the code, or so we can use the existing controller. There you can enter the code and build/run the application.
Install the Dapper, Microsoft.Data.SqlClient Library through NuGet Package Manager

The Visual Studio software provides the NuGet Package manager option to install the package directly to the solution.

In Visual Studio Select Tools > NuGet Package Manager > Manage NuGet Packages for the solution. The below screenshot shows how to open the NuGet Package Manager.

Search for the specific package Dapper, Microsoft.Data.SqlClient using the search box on the upper left. Select a package from the list to display its information, enable the Install button and a version-selection drop-down, as shown in the below screenshot. The NuGet package will be installed for your project and reference will be added, as seen in the screenshot below.

In the above image, we can see the list of the related search items. We need to select the required option to install the package to the solution.

Add Connection String
In solution explorer select a file appsettings.json double click on this file to open "Add" connection string as shown below.
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "DefaultConnection": "Data Source=.;Initial Catalog=Companies-DB;Integrated Security=True;Pooling=False;Encrypt=false"
  }
}


Add Models class
Right-click the Models folder > Add > Class. Name the file Company.cs
using System.ComponentModel.DataAnnotations;

namespace CURDWithDapperCore6MVC_Demo.Models
{
    public class Company
    {
        public int Id { get; set; }
        [Display(Name ="Company Name")]
        public string CompanyName { get; set; }

        [Display(Name = "Company Address")]
        public string CompanyAddress { get; set; }

        public string Country { get; set; }

        [Display(Name = "Glassdoor Rating")]
        public int GlassdoorRating { get; set; }
    }
}


Add DBContext Folder and DapperContext Class
Right click on Project in Solution Explorer>Add New>New Folder. Rename this folder to DBContext. Now right click on DBContext folder > Add> New Item> C# class name this class DapperContext.

using Microsoft.Data.SqlClient;
using System.Data;

namespace CURDWithDapperCore6MVC_Demo.DBContext
{
    public class DapperContext
    {
        private readonly IConfiguration _configuration;
        private readonly string _connectionString;
        public DapperContext(IConfiguration configuration)
        {
            _configuration = configuration;
            _connectionString = _configuration.GetConnectionString("DefaultConnection");
        }
        public IDbConnection CreateConnection() => new SqlConnection(_connectionString);
    }
}


Add Repositories Folder and ICompanyRepository Interface

Right click on Project in Solution Explorer>Add New>New Folder. Rename this folder to Repositories. Now right click on DBContext folder > Add> New Item>C# Interface and name this interface ICompanyRepository.
using CURDWithDapperCore6MVC_Demo.Models;

namespace CURDWithDapperCore6MVC_Demo.Repositories
{
    public interface ICompanyRepository
    {
        Task<IEnumerable<Company>> GetCompanies();
        Task<Company> GetCompany(int? id);
        Task CreateCompany(Company company);
        Task UpdateCompany(int id, Company company);
        Task DeleteCompany(int id);
    }
}


Add Company Repository class to Implement Interface

Right click on Repositories Add> New Item>C# class and name this class to CompanyRepository.
using CURDWithDapperCore6MVC_Demo.DBContext;
using CURDWithDapperCore6MVC_Demo.Models;
using Dapper;
using System.Data;

namespace CURDWithDapperCore6MVC_Demo.Repositories
{
    public class CompanyRepository : ICompanyRepository
    {
        private readonly DapperContext context;

        public CompanyRepository(DapperContext context)
        {
            this.context = context;
        }

        public async Task<IEnumerable<Company>> GetCompanies()
        {
            var query = "SELECT * FROM Companies";

            using (var connection = context.CreateConnection())
            {
                var companies = await connection.QueryAsync<Company>(query);
                return companies.ToList();
            }
        }

        public async Task<Company> GetCompany(int? id)
        {
            var query = "SELECT * FROM Companies WHERE Id = @Id";

            using (var connection = context.CreateConnection())
            {
                var company = await connection.QuerySingleOrDefaultAsync<Company>(query, new { id });
                return company;
            }
        }

        public async Task CreateCompany(Company company)
        {
            var query = "INSERT INTO Companies (CompanyName, CompanyAddress, Country,GlassdoorRating) VALUES (@CompanyName, @CompanyAddress, @Country, @GlassdoorRating)";

            var parameters = new DynamicParameters();
            parameters.Add("Name", company.CompanyName, DbType.String);
            parameters.Add("Address", company.CompanyAddress, DbType.String);
            parameters.Add("Country", company.Country, DbType.String);
            parameters.Add("Country", company.GlassdoorRating, DbType.Int32);

            using (var connection = context.CreateConnection())
            {
                await connection.ExecuteAsync(query, parameters);
            }
        }

        public async Task UpdateCompany(int id, Company company)
        {
            var query = "INSERT INTO Companies (CompanyName, CompanyAddress, Country,GlassdoorRating) VALUES (@CompanyName, @CompanyAddress, @Country, @GlassdoorRating WHERE Id = @Id)";
            var parameters = new DynamicParameters();
            parameters.Add("Name", company.CompanyName, DbType.String);
            parameters.Add("Address", company.CompanyAddress, DbType.String);
            parameters.Add("Country", company.Country, DbType.String);
            parameters.Add("Country", company.GlassdoorRating, DbType.Int32);
            using (var connection = context.CreateConnection())
            {
                await connection.ExecuteAsync(query, parameters);
            }
        }
        public async Task DeleteCompany(int id)
        {

            var query = "DELETE FROM Companies WHERE Id = @Id";
            using (var connection = context.CreateConnection())
            {
                await connection.ExecuteAsync(query, new { id });
            }
        }
    }
}

Add a controller
In Solution Explorer, right-click Controllers > Add > Controller.
In the Add New Scaffolded Item dialog box, select MVC Controller – MVC Controller with read/write actions > Add.
In the Add New Item - Companies dialog, enter CompaniesController.cs and select Add.
Replace the contents of Controllers/ CompaniesController.cs with the following code:

Add a view

Right-click on the Action in CompaniesController, and then Add View.
In the Add New Scaffolded Item dialog:
    Select Razor View Select Add
    View Name: Index
    Template: List
    Model Class: Company
    Select Add

Replace the contents of the Views/Companies/Index.cshtml Razor view file with the following:
@model IEnumerable<CURDWithDapperCore6MVC_Demo.Models.Company>

@{
    ViewData["Title"] = "Index";
}

<h2 class="text-capilization text-center">List of Companies</h2>

<p>
    <a asp-action="Create" class="btn btn-primary"> <i class="fa-solid fa-circle-plus"></i> Add New</a>
</p>
<table class="table table-bordered">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Id)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.CompanyName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.CompanyAddress)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Country)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.GlassdoorRating)
            </th>
            <th>Action(s)</th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Id)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.CompanyName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.CompanyAddress)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Country)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.GlassdoorRating)
            </td>
            <td>
                 <a href="@Url.Action("Details",new { id=item.Id})" class="btn btn-sm btn-primary"><i class="fa-solid fa-eye"></i></a>
                 <a href="@Url.Action("Edit",new { id=item.Id})" class="btn btn-sm btn-info"><i class="fa-solid fa-pen-to-square"></i></a>
                 <a href="@Url.Action("Delete",new { id=item.Id})" class="btn btn-sm btn-danger"><i class="fa-solid fa-trash"></i></a>
            </td>
        </tr>
}
    </tbody>
</table>

Note: Similarly Add all action view like Details, Create, Edit and Delete
Now its time to build and run your application Ctrl+F5

 

The above article has taught us. How we can use dapper with repository pattern. Dapper is Micro ORM whereas Entity Framework is ORM. Dapper is faster than entity framework. Hope you enjoyed the article. Happy Coding.



ASP.NET MVC Hosting - HostForLIFEASP.NET :: Working With Areas In MVC

clock November 30, 2022 07:27 by author Peter

The primary purpose of areas in MVC is to separate and manage Model, View, Controller, Themes and routing registration file into separate sections. In other words, areas serve as a technique for dividing and managing a large Application into well managed smaller modules with the separate M-V-C in each module.


Why to use areas in MVC Application?
If you are building a CRM Application for a small Educational Consultancy with multiple business units such as Registration on Arrival, Information Gathering by Receptionist, Updates by Consular, Documentation Management, Interview Preparation, Billing, and Report Generation by different departments etc. Each of these units have their own logical components views, controllers and models. In this scenario, you can use ASP.NET MVC areas to physically partition the business components in the same project.

It is also possible that we can have large projects that uses MVC, then we need to split the Application into smaller units called areas that isolates the larger MVC Application into smaller functional groupings. A MVC Application can contain several MVC structures (areas).

Areas are the small functional units with its own set of Model, View and Controller

    MVC Application can have any number of areas.
    Each area has its own controllers, models and views.
    Areas are put under separate folders called areas.

Today, we will be creating a new ASP.NET MVC Application and define a new area inside the project.

Creating new MVC Application


Step 1
Open Visual Studio.

Step 2
Create an ASP.NET Web Application with MVC template, as shown below.

Step 3
In Solution Explorer, right-click on the project and click Add. Select areas to add an area.

Step 4
Enter the name for the area, such as "Consular" or “SuperAdmin”.

Adding Controller for Area
Now, let’s add a controller in Area.

Step 1
Right-click on the Controller in your article area to add a controller.

Step 2
Select "MVC 5 Empty Controller.


Step 3
Provide controller name as "ManageInterviewController”. Now, your Area folder should look, as shown below.

Adding Views for Area
We have successfully added a controller for our area. Now, let’s add a view for the area.

Step 1
Right-click on the "Index" method of ManageInterviewConsular Controller and click on Add View.

Step 2
Enter the view name and select Layout page.

Step 3
Generate some content in the View of Index method, as shown below.


Index g (table table-hover table-bordered table-responsive" >Time< /tr>Kathmandu< /tr> " "picture_x0020_6"="">
 
Area Registration
Step 1
Open the "Global.asax" file.

Step 2
Add the code given below in your Application_Start() method.

AreaRegistration.RegisterAllAreas();


Till here, we have successfully added an area. Inside Area is the one, where we have added aController and a View for Index method.
Now, let’s add a link in Navbar of an Application to navigate to the view, which we created just now.

Step 1
Open the project view Layout file.

Step 2
Modify the <ul> </ul> in the layout file, as shown in the code given below.

Step 3
Debug the Application and open List Interview link, as shown below.

Let’s notice the URL
As highlighted, to invoke the controller of the area, we need to use

Baseurl/Areaname/Controller/{actionname}




ASP.NET MVC Hosting - HostForLIFEASP.NET :: Implement PRG Pattern in MVC Architecture

clock November 25, 2022 05:53 by author Peter

This article requires a basic understanding of MVC architecture and design pattern concepts. If you are very new to MVC then I suggest you understand MVC architecture before continue this article.


Let's talk the PRG design pattern and it's uses. PRG stands for Post Redirect Get. Fine, but why? Let's implement one small MVC application and we will see the real problem and scenario where we can use the PRG design pattern.

The problem is very common, and I am sure in your programmer and user life, you have encountered this situation. Let's consider, we have one Web form to collect user's information, very simple and clean. The user has filled in the necessary fields and hit the submit button. It is obvious it will hit some action belonging to some controller (defined in the controller) to save data in the database (or somewhere).

We are assuming that we are a good programmer (Really? Let's see. Haha..) and the data has been submitted. Now the user has hit the refresh button. Oh suck, it has called the action again? Let's see it in reality.

My Simple Model
This is kept simple intentionally because our point of discussion is different.
    namespace MVC.Models 
    { 
        public class person 
        { 
            public string _name{get;set;} 
            public string _surname { get; set; } 
            public int _age { get; set; } 
        } 
    } 


Here is my view

Which is a strong type in nature and I am targeting the “SaveData” action for the “person” controller.
    <%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<MVC.Models.person>" %> 
    <!DOCTYPE html> 
    <html> 
    <head runat="server"> 
        <meta name="viewport" content="width=device-width" /> 
        <title>person</title> 
    </head> 
    <body> 
        <div> 
            <% using (Html.BeginForm("SavePerson","person")){ %> 
                Name : <%= Html.TextBox("_name") %> <br /> 
                Surname: <%= Html.TextBox("_surname") %> <br /> 
                Age: <%= Html.TextBox("_age") %><br /> 
                <input value="Register" type="submit" /> 
            <% } %>  
        </div> 
    </body> 
    </html> 


Now, let's see the controller implementation. In the person controller we have defined two actions, the AddNew() action will return this person view and the SavePerson() action will collect form data using a model binding technique.
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Web; 
    using System.Web.Mvc; 
    using MVC.Models; 
    namespace MVC.Controllers 
    { 
        public class personController : Controller 
        { 
            public ActionResult AddNew() 
            { 
                return View("person"); 
            } 
            public ActionResult SavePerson([Bind] person p) 
            { 
                return Content("Data Saved"); 
            } 
        } 
    }

Now, if we hit the submit button as in the following:

Then we will see the following screen and we are seeing that the data has come as the action's parameter.

And we will get the result as in the following.

Now, let's hit the refresh button of the browser and let's see the result.

 

And if we press retry then it will hit the controller's action again.

Since it's hitting the same controller again, there might a great chance to save a duplicate record in the database that we don't want at all.

Then what is the solution? The PRG design pattern. How will it solve the problem? When we submit a form's data it makes a POST request to the server and we know that the POST method is harmful in the page reload operation.

So, the trick is that we will make a POST request to the server and the server will transfer the request into the GET request.

Then the result page will display by the GET request and when we make another browser refresh the next time, it will make a GET request to the server, which is not at all harmful.

Ok, we have learned the mechanism. Now let's implement it in an application. For that we need to make a small change in the controller.
    namespace MVC.Controllers 
    { 
        public class personController : Controller 
        { 
            public ActionResult AddNew() 
            { 
                return View("person"); 
            } 
            public ActionResult SavePerson([Bind] person p) 
            { 
               return RedirectToAction("PRG", "person"); 
            } 
            public ActionResult PRG() 
            { 
                return Content("Data Saved"); 
            } 
        } 
    }


We have added another action named “PRG” and from the SavePerson() action we are redirecting the context to the PRG() action using the “RedirectToAction()” method.

Now when we refresh again it will hit the “PRG()” action, not the “SavePerson()” action.

Though this type of redirection eats server resources, the business needs and security comes before performances. Happy day.



ASP.NET MVC Hosting - HostForLIFEASP.NET :: Single Sign-On Using ASP.NET MVC And ASP.NET Core

clock November 21, 2022 07:28 by author Peter

What is single sign-on (SSO)?
Users must authenticate themselves to access pages protected by a web application, and if a user accesses multiple web applications, they must be authenticated. You must log in to each application separately.

Single Sign-on using ASP.NET MVC and ASP.NET CORE
Interested in using single sign-on (SSO) for your ASP.NET MVC app? You're in the right place. There are many reasons to use SSO for custom apps owned by the same organization.

    Improved user experience.
    Reduce development time.
    Improved security.

These are all good reasons.

Another thing I like about SSO is that it allows me to update large code bases in small increments instead of all at once.

As? Suppose you want to migrate an app written in ASP.NET MVC 5 to ASP.NET Core MVC. Instead of rewriting everything at once, you can migrate one service at a time. By implementing SSO between two apps, you can effectively connect the two apps as if they were one app.

This tutorial simulates such a scenario by implementing his SSO in an MVC 5 app and a .NET Core app. Along the way, you'll also learn about the differences in how the two platforms implement authentication.

Find the ASP.NET MVC 5 App

Access an existing MVC 5 app from GitHub instead of building a project from scratch. Clone or download this project (https://github.com/oktadev/aspnet-mvc-crud-example) and open the solution in Visual Studio.

Web.config file has some app settings used by programmers to configure authentication with the Open ID Connect server provided by Okta:
<add key="okta:ClientId" value="{yourClientId}" />
<add key="okta:ClientSecret" value="{yourClientSecret}" />
<add key="okta:OktaDomain" value="https://{yourOktaDomain}" />


For this tutorial, you'll need to switch these values ​​to your own Okta instance. Sign in to your Okta domain if you already have an account, or sign up for a forever free developer account if you don't already have one.

After signing in to Okta, register your client application.

    Click Applications on the top menu.
    Click Add Application.
    Select Web and click Next.
    Enter SSO MVC 5 for Name.
    For the Grant type allowed check the Implicit (Hybrid) checkbox
    And last click on DONE

The application has been created, but we still need to add something. Select Edit and add http://localhost:8080/Account/PostLogout to the logout redirect URI list and click Save.

On the next screen, you will see a summary of your settings. Under the General Settings section, you will see the Client Credentials section. Update the SSO settings in Web.config with your client ID and client secret. Next, go to the main page of your Okta dashboard, copy the organization URL shown in the top left corner, and paste it into Okta.

OktaDomain app settings in Web.config.

At this point, you should be able to run your app and sign in and out using OpenID Connect. If you're interested, take a look at Startup.cs to see how the authentication middleware is configured.

Find the ASP.NET Core App

Now that you're using Okta to log into your MVC 5 app, adding SSO to your second app is trivial.

First, download or clone this .NET Core app from GitHub.(https://github.com/oktadeveloper/okta-aspnetcore22-crud-example) If opening in Visual Studio, change the debug target from IIS Express to LiveMusicFinder.

This will run your app through the Kestrel web server on port 5001 (for https).

Go back to your Okta admin panel and register this application.
    click on Applications at top of the menu
    Then click on Add Application
    And select Web and click Next
    Enter SSO Core MVC for the Name
    Replace Base URIs with https://localhost:5001/
    Replace Login redirect URIs with https://localhost:5001/authorization-code/callback
    Click Done

Once complete, you'll be taken to the General Settings tab of the app. In this tab, click the Edit button and add an entry to the Signout Redirect URI as https://localhost:5001/signout/callback.

Then click Save.

Copy the Client ID and Client Secret from the Client Credentials section of the next page and update your application's appsettings.json file.
"Okta": {
  "ClientId": "{yourClientId}",
  "ClientSecret": "{yourClientSecret}",
  "OktaDomain": "https://{yourOktaDomain}",
  "PostLogoutRedirectUri": "https://localhost:5001/"
},


While editing the settings, update the OktaDomain settings to match what you entered in your MVC 5 app's Web.config. Also change the PostLogoutRedirectUri to https//local host:5001/.

That's really it. When you sign in to either app, click the Sign In link in the other app to automatically sign you in without prompting for your password.

(If you're inexplicably testing this using Internet Explorer and Visual Studio's auto-launch feature, make sure you're opening her second app in a tab in her window in the first browser. . Each browser window is isolated from the others due to Visual Studio's habit of launching IE.)
How single sign-on works in ASP.NET MVC 5 and ASP.NET Core

We've seen how easy it is to enable SSO in two ASP.NET apps, but what's really going on behind the scenes to make it work?

Suppose you first navigate to App 1 and click Sign In. App 1 redirects to Okta IdP (Identity Provider) where it signs in. When you log in, a cookie from Okta's domain is set in your browser. This cookie keeps you logged into Okta. Okta then returns to App 1 with the token it uses to complete the sign-in process. At this point, her cookie is also set on the App 1 domain. Here's a diagram to explain the states:


Then open app 2 in another tab in the same browser. Click Sign In and you will be redirected back to the Okta IdP. However, this time we still have a valid cookie, so we are already logged into the IdP. So instead of showing a login screen, Okta simply redirects to App 2 with the token needed to complete the local login process. A cookie is set on the domain of app 2 and you can log in from anywhere.

Note that Single sign-out_ is not supported by Okta as of this writing. When you log out of App 1, the cookies in App 1 are deleted and a quick call is made to the Okta IdP, which deletes the cookies. However, the App 2 cookie remains and you remain signed in to App 2 until you click Sign Out or the cookie expires. The default expiration is 30 days.
Explain ASP.NET OpenID Connect Flow

As you may have noticed, when I set up the configuration for my MVC 5 app I had to check the box to enable the implicit (hybrid) grant type, but not for .NET Core apps was.

When the OpenID Connect middleware was written for his MVC 5 years ago (long time ago in the software world), the OpenID Connect hybrid flow was implemented. This flow requires the IdP to pass an authorization code and ID token to the MVC 5 app submission. When redirecting the user to your app.

When the OpenID Connect middleware was written for .NET Core, it implemented a more secure authorization code flow. In this case the IdP should only return an authorization code and the middleware should get the ID token via a backchannel request to his IdP. This means that the ID token is not exposed to browsers. Note that if you pass sensitive information in an ID token, in MVC 5 this token will be returned to your app via the browser. This is not a problem when enabling SSO for him for .NET Core apps.



ASP.NET MVC Hosting - HostForLIFEASP.NET :: Custom Error Page in ASP.NET MVC

clock November 8, 2022 09:29 by author Peter

Procedure
    First add an Error.cshtml page (View Page) to the Shared Folder if it does not already exist.
    Add or modify the Web.config file and set the Custom Error Element to On.
    Add a specific Action Controller and View for showing the HTTP Status Code.
    Add an [HandleError] attribute to the Targeted Action Method.

Note: When we are working on an internet application, by default it contains an Error.cshtml file.
Add a View Page. Right-click Solution Explorer, click View Folder, go to Shared Folder and name it Error.cshtml.

 

Then design the Error Page depending on your requirements, if it already exists then modify it to suit your needs.

Error.cshtml
    @model System.Web.Mvc.HandleErrorInfo  
      
    @{  
        ViewBag.Title = "Error";  
    }  
      
    <div style="background-color: #A52A2A; color: White; height: 10px;">  
    </div>  
    <div style="background-color: #F5F5DC; color: White; height: 170px;">  
        <div style=" padding:20px;">  
            <h3>  
                Application Error:</h3>  
            <h4>  
                Sorry, an error occurred while processing your request.  
            </h4>  
            <h6>@Html.ActionLink("Go Back To Home Page", "Index", "Home")</h6>  
            <br />  
            <br />  
        </div>  
    </div>  
    <div style="background-color: #A52A2A; color: White; height: 20px;">  
    </div> 



Go to Web.config file


    There are two Web.config files in an ASP.NET MVC Project.
    Go to Web.config file at the root directory.

    Go to Root Directory, Web.config, then System.Web, and click CustomError.
    Set it to On.

    Add this line.
        <customErrors mode="On">  
        </customErrors>  
    Run the application and search for anything, or Link that is not available.

As example:
    Try any Link or try to navigate to any View that is available.


    Then again try another link that is not available or modify the preceding link and watch the difference.
    This will show you your Customized Error page rather than a default page.

Step: Try to run or Browse for a View Page that is not available (A Controller whose View is not added.).
But before that, add this Attribute to the Controller.

At the Controller:
    [HandleError]  
    public ActionResult Index()  
    {  
       return View();  
    } 


Repeat Step: Try to run or Browse for a View Page that is not available (A Controller whose View is not added.).

If you add the Attributes [HandleError] to any Action Method, you will be shown your own Customized Error page written now, rather than the default Error Page.
Now add specific error pages based on the HTTP Status Code.
Such as one specific Error Page to show when the HTTP Status Code is 404.
Add a Controller to the Controller Folder and name it Error.


Add some action method to the Controller.

    Error Controller
        using System;  
        using System.Collections.Generic;  
        using System.Linq;  
        using System.Web;  
        using System.Web.Mvc;  
          
        namespace MvcApplication3.Controllers  
        {  
            public class ErrorController : Controller  
            {  
                //  
                // GET: /Error/  
          
                public ActionResult Index()  
                {  
                    return View();  
                }  
          
                public ActionResult NotFound()  
                {  
                    return View();  
                }  
            }  
        }  


Add a View Named NotFound to the Shared Folder like, as you have done earlier.
Note: We are adding this View to the Shared Folder, because Views inside Shared Folder is available to the complete application.
Right-click then select View, then go to Shared Folder and Add a View named NotFound.

 

And Design the View depending on your requirements.

Not Found.cshtml
    @{  
        ViewBag.Title = "NotFound";  
    }  
      
    <div style="background-color: #A52A2A; color: White; height: 10px;">  
    </div>  
    <div style="background-color: #F5F5DC; color: White; height: 170px;">  
        <div style=" padding:20px;">  
            <h3>  
                Application Error:</h3>  
            <h4>  
                Sorry, The Page, You are Looking for is not found.  
            </h4>  
            <h6>@Html.ActionLink("Go Back To Home Page", "Index", "Home")</h6>  
            <br />  
            <br />  
        </div>  
    </div>  
    <div style="background-color: #A52A2A; color: White; height: 20px;">  
    </div>  


Again go to the Root folder, then Web.config file. Go inside System.web and modify it.
    <customErrors mode="On">  
       <error statusCode="404" redirect="~/Error/NotFound"/>  
    </customErrors>  


Explanation

Now run the application, try to navigate to an unavailable View and you will see the Customized Error Page rather than the default Error Page.

Default Error Page: Example

 

Now, if any error occurs then the Customized Error Page will be shown.
This was all about how to display a custom error page in ASP.NET MVC.

Similarly, design all other Custom Error page depending on HTTP Status Code.

Note: The preceding information is gathered by me depending on the results of studying, experience, Internet Browsing, and Video Tutorials.



ASP.NET MVC Hosting - HostForLIFEASP.NET :: Custom SQL Server Pagination with .Net Core MVC and JQuery

clock November 2, 2022 08:27 by author Peter

The question is, why do we need SQL Pagination when we already have built-in paging functionality in Grid View or JQuery Data table.


Answer is èSometimes it's not a good habit to load all the data over the network, but instead to transfer only the data required, to improve performance. For that we have SQL paging. Pass only a Page Index and Page Size to load the required data.

To do this, I created the following Stored Procedure:
=============================================
-- Author: Nilachal Sethi
-- Create Date: Oct 31, 2022
-- Description: Get full List By Pagination
-- =============================================
CREATE PROCEDURE [dbo].[ListData]

       @PageSize as int=1000,
       @Caret as int=0,
       @Option varchar(100) = Null

AS
BEGIN

   Declare @TotalRecord int
SELECT @TotalRecord =COUNT(ID) FROM JobOrder
                     OFFSET @PageSize * (@Caret)ROWS FETCH NEXT @PageSize ROWS ONLY


              SELECT @TotalRecord AS TotalRecord,* FROM JobOrder
                     ORDER BY DateTaken DESC
                     OFFSET @PageSize * (@Caret)ROWS FETCH NEXT @PageSize ROWS ONLY
     END;

Now the Controller is:
[HttpGet]
public IActionResult GetJobOrderGrid(int? pagesize, int? caret)
{
    string responseString = "";
    var response = webApiMethodsForDBAction.GetAsyncCall(webApiUrl +"URL?Pagesize=" + pagesize + "&Caret=" + caret);
    int StatusCode = Convert.ToInt32(response.StatusCode);
    if (StatusCode == 200)
    {
        responseString = response.Content.ReadAsStringAsync().Result;

    }
    return Json(responseString);
}


Now the View is:
<div id="JobGrid">
    <input type="hidden" id="hidcurrentindexemp" value="0" />
    <input type="hidden" id="hidemppagesize" value="10" />
    <input type="hidden" id="hiddenTotalRecord" value="" />
    <div class="row">
        <div class="col-md-12 m-grid__item">

            <div id="JobDiv" class="">

            </div>
            <div class="clearfix"></div>
            <div class="pagination-content clearfix" id="qemp"></div>

        </div>
    </div>
</div>
<script src="@Url.Content(" ~/MainCustomer/js/FullCustomer.js")"></script>

<script type="text/javascript">
    $(document).ready(function () {
            GetJobOrderList();
    });
</script>


Now the JQuery is:
For making Table And Pagination
function GetJobOrderList() {
    $.ajax({
        url: '/Area/Controller/ActionName',
        type: "GET",
        data: { pagesize: $('#hidemppagesize').val(), caret: $('#hidcurrentindexemp').val() },
        dataType: "json",
        async: true,
        beforeSend: function () {
            $("#divLoading").show();
        },
        success: function (data) {

            var Job = JSON.parse(data);
            if (Job === '') {
                window.location.reload();
            }
            var JobList = Job.thisList;
            var TotalRecord = Job.thisList[0].TotalRecords;
            var job_id = Job.thisList[0].Id;
            $('#hiddenTotalRecord').val(TotalRecord);
            var grid = '';
            grid += '<div class="main-container table-responsive table-container"><table class="table table-striped table-hover table-bordered" id="JobOrderTable"><thead> <tr><th>Action</th><th>Job Title</th><th >Customer Name </th><th>Stages </th><th>Start Date</th><th>Location</th><th>End Client</th><th>#Position</th><th>Status </th></tr> </thead>';
            grid += '<tbody>';
            if (data === null) {
                grid += '<tr><td colspan="9" >No Records Found.<td></tr>';
            }
            else {
                $.each(JobList, function (d, value) {
                    grid += ' <tr><td>' + (value.JobTitle === "" ? "N/A" : value.JobTitle) + '</td><td>' + (value.CustomerName === "" ? "N/A" : value.CustomerName) + '</td><td>' + (value.JoborderStage === "" ? "N/A" : value.JoborderStage) + '</td><td>' + (value.FormattedStartDate === "" ? "N/A" : value.FormattedStartDate) + '</td><td>' + (value.Location === null ? "N/A" : value.Location) + '</td><td>' + (value.Positions === "" ? "N/A" : value.Positions) + '</td><td>' + (value.IsActive === "Active" ? "" : "") + '</td></tr>';
                });
            }
            grid += '</tbody></table>';
            Pagination($('#hiddenTotalRecord').val(), $("#hidcurrentindexemp").val(), $("#hidemppagesize").val(), "#qemp", "qemp");
            $("#JobDiv").html(grid);
            $("#divLoading").hide();
        },
        error: function (xhr, textStatus) {
            if (xhr.status === 401) { window.location.reload(); }
            else {
                    $.notify('please try again!', "error");
                $("#divLoading").hide();
            }
        }
    });
}


For Click Page Function

function Search_qemp(index) {
    $("#hidcurrentindexemp").val(index);
    GetJobOrderList();
}

Main Pagination JS:
function Pagination(totalrecord, currentindex, pagesize, div, Type) {
    currentindex = parseInt(currentindex);
    totalrecord = parseInt(totalrecord);
    pagesize = parseInt(pagesize);
    var pagestring = '';
    $(div).html("");
    var pagerlink = Math.ceil(totalrecord / pagesize);
    var lastindex = pagerlink - 1;
    if (totalrecord === 0) {
        $(div).append('<p>Displaying 0 out of 0 items </p>');
    }
    else if (totalrecord > 0) {
        if (currentindex === lastindex) {
            if (currentindex === 0) {
                $(div).append('<p>Displaying ' + 1 + ' to ' + totalrecord + ' out of ' + totalrecord + ' items </p>');
            }
            else {
                $(div).append('<p>Displaying ' + parseInt(1 + (pagesize * (currentindex - 1) + parseInt(pagesize))) + ' to ' + totalrecord + ' out of ' + totalrecord + ' items </p>')
            }
        }
        else {
            $(div).append('<p>Displaying ' + parseInt(pagesize * currentindex + 1) + ' to ' + parseInt(pagesize * currentindex + parseInt(pagesize)) + ' out of ' + totalrecord + ' items </p>')
        }
        $(div).append('');
        if (totalrecord === 0) {
            pagestring = pagestring + '<li class="paginate_button page-item"><a class="page-link number">First</a></li><li class="paginate_button page-item"><a class="page-link number">Previous</a></li>' +
                '<li class="paginate_button page-item"> No Record Found </li><li class="paginate_button page-item"><a class="page-link number">Next</a></li><li class="paginate_button page-item"><a class="page-link number">Last</a></li>';
        }
        else {
            if (currentindex === 0) {
                pagestring = pagestring + '<li class="paginate_button page-item"><a class="page-link number">First</a></li>' +
                    '<li class="paginate_button page-item"><a class="page-link number">Previous</a></li>';
            }
            else {
                pagestring = pagestring + '<li class="paginate_button page-item"><a class="page-link number" onclick="Search_' + Type + '(0);">First</a></li>' +
                    '<li class="paginate_button page-item"><a class="page-link number" onclick="Search_' + Type + '(' + parseInt(currentindex - 1) + ');">Previous</a></li>';
            }
            var counter = 0;
            var intial = 0;
            if (parseInt(currentindex) < 5) {
                intial = 0;
            }
            else {
                intial = parseInt(currentindex) - 3;
            }
            for (var i = intial; i < pagerlink; i++) {
                var j = i + 1;
                if (i === currentindex) {
                    pagestring = pagestring + '<li class="paginate_button page-item number active"> <a class="page-link number" value="' + j + '">' + j + '</a></li>';
                }
                else {
                    pagestring = pagestring + '<li class="paginate_button page-item"> <a class="page-link number" onclick="Search_' + Type + '(' + i + ');" value="' + j + '">' + j + '</a> </li>';
                }
                if (counter === 5)
                    break;
                counter++;
            }
            if (currentindex === lastindex) {
                pagestring = pagestring + '<li class="paginate_button page-item"><a class="page-link number">Next</a></li>' +
                    '<li class="paginate_button page-item"><a class="page-link number">Last</a></li>';
            }
            else {
                var nextindex = (parseInt(currentindex) + 1);
                pagestring = pagestring + '<li class="paginate_button page-item"><a class="page-link number" onclick="Search_' + Type + '(' + nextindex + ');">Next</a></li>' +
                    '<li class="paginate_button page-item"><a class="page-link number" onclick="Search_' + Type + '(' + lastindex + ');">Last</a></li>';
            }
        }
        pagestring = '<div class="pagination-right"><nav><ul class="pagination float-md-right float-lg-right">' + pagestring + '</ul></nav></div>';
        $(div).append(pagestring);
    }
}

Now run the application.
Here we go…..

If you have any problem then please let me know.



ASP.NET MVC Hosting - HostForLIFEASP.NET :: View Variables In .NET Core MVC

clock October 28, 2022 07:55 by author Peter

The previous article, View Variables in .NET MVC, planned to discuss View Variables for both .NET MVC and .NET Core MVC. However, after finishing the .NET MVC part, I realized that the article is too long if I add another part for .NET Core. Therefore, I separate that part into this new article. So, the content structure will be exactly the same as the previous one for .NET MVC.


This will be the contents of this article,
    .NET Core MVC
        Setup Environment for Code Testing
        What ViewBag, ViewData, TempData, and Session are
        How ViewBag, ViewData, TempData, and Session Work
            ViewBag and ViewData
            TempData
            Session
        Difference between .NET MVC and .NET Core MVC for View Variables
            .NET MVC TempData supported by Session by Default
            .NET Core MVC TempData supported by CookieTempDataProvider by default
            .NET Core MVC TempData supported by Session after Session Enabled

A - Setup MVC Environment for Code Testing
Step 1 - Create a .NET Core MVC ap
p
We use the current version of Visual Studio 2019 16.9.4 and .NET Framework 4.8 to build the app,

Start Visual Studio and select Create a new project.

  • In the Create a new project dialog, select ASP.NET Core Web App (Model-View-Controller) > Next.
  • In the Configure your new project dialog, enter Core MVC for Project name > Next
  • In the Additional Information dialog, select .NET 5.0 > Create

Step 2 - Add ViewBag, ViewData, TempData, and Session
In Controller, update HomeController/Index action,
public class HomeController: Controller {
    private readonly ILogger < HomeController > _logger;
    public HomeController(ILogger < HomeController > logger) {
        _logger = logger;
    }
    public IActionResult Index() {
        List < string > Student = new List < string > ();
        Student.Add("Peter");
        Student.Add("Scott");
        Student.Add("Mark");
        this.ViewData["Student"] = Student;
        this.ViewBag.Student = Student;
        this.TempData["Student"] = Student;
        //this.Session["Student"] = Student;
        return View();
    }......
}

Note
Different from .NET MVC, where the Session State is supported by default, in .NET Core MVC, the Session State is not supported by default before we add it into the app. So, at this point, before we add the Session state, the Session will not work.  We will discuss this point, especially in Section D.

In View/Homw/Index.cshtml,

@{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

<br>
<br>

<ul>
    <b>ViewBag</b>
    @foreach (var student in ViewBag.Student)
    {
        <li>@student</li>
    }
</ul>
<ul>
    <b>ViewData</b>
    @foreach (var student in ViewData["Student"] as List<string>)
    {
        <li>@student</li>
    }

</ul>
<ul>
    <b>TempData</b>
    @foreach (var student in TempData["Student"] as List<string>)
    {
        <li>@student</li>
    }
</ul>
@*<ul>
    <b>Session</b>
    @foreach (var student in Session["Student"] as List<string>)
    {
        <li>@student</li>
    }
</ul>*@


Note
The Session Variable in the view comments out, too.

B - What ViewBag, ViewData, TempData, and Session are
ViewBag, ViewData, TempData, and Session are the options to send value from controller to view or to other action method/pages.

1. They are the properties of Controller in MVC Core
Like .NET MVC, in .NET Core MVC, ViewBag, ViewData, TempData, and Session are the properties of the Controller Class.

However, different from .NET MVC, where ViewBag, ViewData, and TempData are the properties of ControllerBase class, which is the parent of the Controller Class; while the Session is the property of Controller class. In .NET Core MVC, they are opposite. ViewBag, ViewData, TempData belong to Controller class directly,

While the Session (HttpContext) is the property of ControllerBase class,

2. Type
They are all the type of Dictionary with the string as key, except ViewBag is dynamic type:
    ViewData --- public Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ViewData { get; set; }
    ViewBag --- public dynamic ViewBag { get; }
    TempData --- public Microsoft.AspNetCore.Mvc.ViewFeatures.ITempDataDictionary TempData { get; set; }
    Session --- public Microsoft.AspNetCore.Http.HttpContext HttpContext { get; }

Note:
ViewBag is a wrapper over ViewData and allows to store and retrieve values using object-property syntax rather than key-value syntax used by dictionary objects. It does so using the dynamic data type feature of .NET.

C - How ViewBag, ViewData, TempData, and Session Work
This part, they are similar to what they are in .NET MVC, we just repeat the conclusion and skip the analysis, and then we open another session D to discuss the difference between .NET MVC and .NET Core MVC.

1. ViewBag and ViewData
They can be used to pass data from controller to view, one way only in the same request.
The difference between ViewBag and ViewData,
    ViewData
        If passing string into ViewData then no need to typecast
        If the passing object in ViewData then you need to typecast it but before that, you need to check if it is not null
    ViewBag
        ViewBag's a dynamic type so not necessary to typecast

2. TempData
TempData is used to transfer data from view to controller, controller to view, or from one action method to another action method of the same or a different controller.

TempData stores the data temporarily and automatically removes it after retrieving a value. i.e., It can be retrieved once, and only once. Finally, we should mention,

    TempData saves into the session so on the expiration of session data loss;
    TempData removes a key value once accessed, you can still keep it for the subsequent request by calling TempData.Keep() method.
    TempData is usually used to pass error messages or something similar.

3. Session
    Session stores data into session
    The session is not similar to TempData to access but you can read as many time as you want
    The session never becomes null until or unless session timeout or session expires.
    The session is not a good practice to use. Used very frequently or store big data, it hits performance

D - Difference between .NET MVC and .NET Core MVC for View Variables
1. The cookie-based TempData provider is used by default to store TempData in cookies.
We know that in .NET MVC TempData is stored in Session state by default. This means the web application must have sessions enabled. However, in .NET Core MVC, the session state is not enabled by default. Luckily, .NET Core 2.0+ provides two TempData providers - Cookie-based and Session State-based while the cookie-based provider is used by default.

TempData providers --- MS

The cookie-based TempData provider is used by default to store TempData in cookies.

The cookie data is encrypted using IDataProtector, encoded with Base64UrlTextEncoder, then chunked. The maximum cookie size is less than 4096 bytes due to encryption and chunking. The cookie data isn't compressed because compressing encrypted data can lead to security problems such as the CRIME and BREACH attacks. For more information on the cookie-based TempData provider, see CookieTempDataProvider.

2. Configure the TempData provider[ref]
The cookie-based TempData provider is enabled by default.
To enable the session-based TempData provider, use the AddSessionStateTempDataProvider extension method. Only one call AddSessionStateTempDataProvider is required.
In Startup.cs,
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();

    services.AddMvc()
         .AddSessionStateTempDataProvider();
    services.AddSession();
}

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

    app.UseSession();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
        endpoints.MapRazorPages();
    });
}


3. Verifications
.NET MVC
Run the app with F12 tools and locate the cookies option. The following figure (Firefox) shows the cookie used by TempData for storing the values. In Firefox, after the app running, type fn F12, under Storage/Cookies, Click the link, you will See: Name: ASP.NET_SessionID (if you run a different app, you probably need to right-click the link and delete all existing cookies),

Click ASP.NET_SeccionId, on the right, you will see the TampData is supported by Session (by default) for .NET MVC,


.NET Core MVC: for default TempData Provider,
Repeat the process above for the .NET Core MVC app,

TempData is supported by CookieTempDataProvider by default for .NET Core MVC,

.NET Core MVC: with Session State
Repeat the process above for the .NET Core MVC app with Session enabled,

TempData is supported by Session for .NET Core MVC after configuration to enable Session and using SessionStateTempDataProvider,



ASP.NET MVC 6 Hosting - HostForLIFE :: Creating ASP.NET MVC APP With WCF Service

clock October 18, 2022 09:37 by author Peter

Use the following to create an ASP.NET MVC APP with a WCF Service using an ADO.NET Entity Data Model:
SQL Server DB -> WCF Service (ORM) -> MVC Application -> User (Browser).

This small app works in a 4-tier architecture as in the following:
    User Tier
    MVC app Tier
    WCF Service Tier
    SQL Server Tier

Project 1: WCF Project
Step 1
Go to VS 2012 and select "File" -> "New Website" then select "WCF Service" then provide the name “WcfMvc”.

Click "OK".

Step 2
Go to the Solution Explorer then go to "WcfMvc application" then right-click on it then seelct "Add" -> "Add new item" -> "Add ADO .Net Entity data model". Then click the "Add" button then place the file in the App_code Folder.

Step 3
Then the Entity Data Model Wizard will be shown. Select "Generate data from database" then click the "Next" button .

Step 4
Choose your data connection. I’m selecting My “ran” database of SqlServer 2012.
Activate the radio button “Yes include the sensitive data in the connection string”.
Save the connection string in the config file by enabling the check box “Save entity connection setting in web.config as:“ then click the "Next" button.

Or

go to the new connection and create your connection then provide the server name then provide the authentication type then select either Windows Authentication or SQL Authentication then provide the database name then click the "Ok" button. A new connection will then be generated.

Activate the Radio Button “Yes include the sensitive data in the connection string”.

Save the connection string in the config file by enabling the check box “save entity connection setting in web.config as: “ then click the "Next" button.

Step 5
Choose which database object you want in your model.

I’m selecting the “Customer” table. The table definition is as follows:
Create table customer
Custno int constraint pk primary key,
custname varchar(30) not null,
custcity varchar(30),
custbalance money);


You can use the above table or create your own table and use it

Then provide a Model Namespace of your choice.. I’m using “ranjeet” Namespace.

Click the "Finish" button.

Please ensure that in the Solution Explorer under the App_code folder the Model.edmx file has been created.

Your entity data model is ready for use.


Step 6
Go to Solution Explorer then expand the App_code Folder then go to the Iservice.cs file.

Step 7
Delete the Getdata() and GetDataUsingDataContract() methods.

Then

I’m writing one method GetCustomer() as follows.

Step 8
Then go to the Sevice.cs file and implement the method declared in the IService.cs interface.

In the Service.cs file right-click the Iservice Interface then select "Implement Interface" -> "Implement Interface".

Delete the already present method in the Service.cs the file.

And write the following code in the “public List<customer> GetCustomer()” method.

“ranEntities1” is a class name given when the connection is created.

Step 9
Open the Service.svc file and now run the project.
A new window will open; copy the URL present in that window and paste it into any text file. This URL will be used in the next project.

Project 2: MVC Application 4
Step 1

Ensure that the WCF project is open then start another instance of VS 2012. Then go to "File" -> "New" -> "Project..." then create an ASP.NET MVC 4 Web Application. Name it “MvcWcfApplication” then click "ok" Button. Then select the Project Template “Internet Application” then click the "Ok" button.

Step 2
Create a Proxy using “Add Service Reference” by right-clicking on MvcWcfApplication in the Solution Explorer.

(Note: Proxy is a class that converts a local request into a remote request.)

A new window will open. Paste the URL that you copied from the WcfMvc project into the Address TextBox then click "Go".

In other words, a proxy class is created successfully..

(Caution: if it has been created and in the project you can’t use the ServiceReference1 namespace Pl then don’t worry; it is a VS 2012 Automation Error. To solve it go to the Solution Explorer then select ServiceReference1 then right-click on it then select "Configure Service Reference". A new window will open then in it uncheck the “Reuse types in referenced assemblies” checkbox..)

A serviceReference1 will added into your project.

Step 3
Now add a new Controller then in Solution Explorer seelct "Controller" then right-click on it then select "Add Controller" (Ctrl+m, Ctrl+c).

Name it DbController. Click the "Add" button.


Step 4
Add the following code in the DbController.cs file.

Please build the project.

Step 5
Now right-click inside the Index() Method then select "Add View" (Ctrl+m, Ctrl+v) then click on “Create a Strongly Typed View” checkbox then select the Model Class we created, in other words “customer (MvcWcfApplication.ServiceReference1)” then select "Scaffold template List"then click the "Add" button.


Step 6
Run the application.
In the browser type: http://localhost:<Port>/Db

And see the results. All the data in the customer table is shown below the using WCF Service.

If you like this then please comment below.



ASP.NET MVC Hosting - HostForLIFEASP.NET :: Generating An Excel File Through A List Of Objects In ASP.NET MVC

clock October 10, 2022 09:21 by author Peter

Today I will show you how to generate an excel file from a list of objects in C#. To do this, several plugins allow you to do this work in a global way. In this work, I will try to create a very simple and generic method to generate an excel file from a list of objects whatever their nature.


Step 1
Create a new ASP.NET MVC project.

Give a name to this project. for example "ExcelGeneratingApp".

Choose the MVC type.

Step 2

Create a class "ExcelLib.cs" in the models folder of the application.

Step 3

Add "ClosedXML" library from Nuget Package Manager.

Add class named "Employee.cs" for example.
using System.ComponentModel;
namespace ExcelGeneratingApp.Models
{
public class Employee
{
[DisplayName("Identity number")]
public int ID { get; set; }
[DisplayName("Full name")]
public string Name { get; set; }
[DisplayName("Age")]
public int Age { get; set; }
[DisplayName("Salary")]
public float Salary { get; set; }
[DisplayName("Department name")]
public string Department { get; set; }

}
}


​Add an "addHeader" method to "ExcelLib.cs" class. This method allows to add and style header of the table in excel file.
using ClosedXML.Excel;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
namespace ExcelGeneratingApp.Models
{
public class ExcelLib
{
// Default Constructor.
public ExcelLib() { }
// Method for adding Header and Title of the table containing List of object values.
public IXLWorksheet addHeader(XLWorkbook wb, List<Object> objs, string title,  string fontFamily = "Sakkal Majalla", string color = "#3498DB")
{
// Sheet initialisation.
var ws = wb.Worksheets.Add("nomDeLaListe").SetTabColor(XLColor.UaBlue);
// font choice.
ws.Style.Font.FontName = fontFamily;
ws.Style.Font.SetFontSize(13);
ws.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
ws.Style.Alignment.WrapText = true;
Object obj = objs.FirstOrDefault();
// Add the model fields to the header of the excel file.
int totalOfFields = obj.GetType().GetProperties().Length; // number of fields in the object.
int numberOfFields = 0;
// Adding the title of table in excel file.
ws.Range(ws.Cell(4, 4), ws.Cell(4, totalOfFields + 3)).Merge().Value = title;
ws.Range(ws.Cell(4, 4), ws.Cell(4, totalOfFields + 3)).Merge().Style.Fill.BackgroundColor = XLColor.FromHtml(color); ;
ws.Range(ws.Cell(4, 4), ws.Cell(4, totalOfFields + 3)).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
ws.Range(ws.Cell(4, 4), ws.Cell(4, totalOfFields + 3)).Style.Font.Bold = true;
ws.Range(ws.Cell(4, 4), ws.Cell(4, totalOfFields + 3)).Style.Font.FontColor = XLColor.WhiteSmoke;
ws.Range(ws.Cell(4, 4), ws.Cell(4, totalOfFields + 3)).Style.Font.FontSize = 18;
//Looping all propeties of the object.
foreach (var prop in obj.GetType().GetProperties())
{
        var displayNameAttribute = prop.GetCustomAttributes(typeof(DisplayNameAttribute), false);
        string displayName = prop.Name;
        if (displayNameAttribute.Count() != 0)
        {
            displayName = (displayNameAttribute[0] as DisplayNameAttribute).DisplayName;
        }
        numberOfFields++;
        ws.Cell(5, totalOfFields - numberOfFields + 4).Value = displayName;
        ws.Cell(5, totalOfFields - numberOfFields + 4).Style.Border.BottomBorder = XLBorderStyleValues.Thin;
        ws.Cell(5, totalOfFields - numberOfFields + 4).Style.Border.LeftBorder = XLBorderStyleValues.Thin;
        ws.Cell(5, totalOfFields - numberOfFields + 4).Style.Border.RightBorder = XLBorderStyleValues.Thin;
        ws.Cell(5, totalOfFields - numberOfFields + 4).Style.Border.TopBorder = XLBorderStyleValues.Thin;
        ws.Column(totalOfFields - numberOfFields + 4).Width = 30;
        ws.Column(totalOfFields - numberOfFields + 4).Style.Font.Bold = true;
}
ws.Range(ws.Cell(5, 4), ws.Cell(5, totalOfFields + 3)).SetAutoFilter();
return ws;
}
}
}


Then add "addBody" method to the "ExcelLib.cs" class.
This method allows to add the list of objects "objs" content to the table in excel file.
It merges the cells of the first column containing the same values.
public IXLWorksheet addBody(IXLWorksheet ws, List<Object> objs)
{
int numberOfFields = 0;
int numberOfRecords = 0;
Object obj = objs.FirstOrDefault();
int totalOfFields = obj.GetType().GetProperties().Length;
string previousValue = "";
int indexOfPreviousValue = 0;

foreach (var item in objs.ToList())
{
  numberOfFields = 0;
  Type myType = item.GetType();
  IList<PropertyInfo> props = new List<PropertyInfo>(myType.GetProperties());

  foreach (PropertyInfo prop in props)
  {
      object propValue = prop.GetValue(item, null);

      numberOfFields++;
      ws.Cell(6 + numberOfRecords, totalOfFields - numberOfFields + 4).Value = propValue;

      ws.Cell(6 + numberOfRecords, totalOfFields - numberOfFields + 4).Style.Font.Bold = true;

      ws.Cell(6 + numberOfRecords, totalOfFields - numberOfFields + 4).Style.Border.BottomBorder = XLBorderStyleValues.Thin;
      ws.Cell(6 + numberOfRecords, totalOfFields - numberOfFields + 4).Style.Border.LeftBorder = XLBorderStyleValues.Thin;
      ws.Cell(6 + numberOfRecords, totalOfFields - numberOfFields + 4).Style.Border.RightBorder = XLBorderStyleValues.Thin;
      ws.Cell(6 + numberOfRecords, totalOfFields - numberOfFields + 4).Style.Border.TopBorder = XLBorderStyleValues.Thin;

      if (numberOfFields == 1 && numberOfRecords == 0)
      {
          previousValue = propValue.ToString();
      }
      else
      {
          if (numberOfFields == 1)
          {
              if (previousValue == propValue.ToString())
              {
                  ws.Range(ws.Cell(6 + numberOfRecords - (1 + indexOfPreviousValue), totalOfFields - numberOfFields + 4), ws.Cell(6 + numberOfRecords, totalOfFields - numberOfFields + 4)).Merge().Value = propValue.ToString();

                  ws.Range(ws.Cell(6 + numberOfRecords - (1 + indexOfPreviousValue), totalOfFields - numberOfFields + 4), ws.Cell(6 + numberOfRecords, totalOfFields - numberOfFields + 4)).Merge().Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
                  ws.Range(ws.Cell(6 + numberOfRecords - (1 + indexOfPreviousValue), totalOfFields - numberOfFields + 4), ws.Cell(6 + numberOfRecords, totalOfFields - numberOfFields + 4)).Merge().Style.Alignment.Vertical = XLAlignmentVerticalValues.Center;
                  indexOfPreviousValue++;
              }
              else
              {
                  previousValue = propValue.ToString();
                  indexOfPreviousValue = 0;
              }
          }

      }


  }
  numberOfRecords++;
}

return ws;
}


Then add a "Generate" method for generating the excel file.
public void Generate(List<Object> objs, string title, string fontFamily = "Sakkal Majalla", string color = "#3498DB")
{
// Workbook creation.
using (XLWorkbook wb = new XLWorkbook())
{
        var ws = addHeader(wb, objs, title);
            ws = addBody(ws, objs);
            wb.SaveAs("C://TestExcelGen.xlsx");
}
}

Step 4
To test this method, we will add some code to the Home controller.
public ActionResult Index()
{
List<Employee> employees = new List<Employee>();
employees.Add(new Employee() { ID = 100 ,Name="PETER", Age=32,Salary=12000,Department="INFO"}) ;
employees.Add(new Employee() { ID = 200 ,Name="SCOTT", Age=24,Salary=10000,Department="CIVIL"}) ;
employees.Add(new Employee() { ID = 300 ,Name="ADAM", Age=20,Salary=11000,Department="INDUS"}) ;
employees.Add(new Employee() { ID = 400 ,Name="ETHAN", Age=21,Salary=9000,Department="INFO"}) ;
ExcelLib excel = new ExcelLib();

excel.Generate(employees.Cast<object>().ToList(), "List of employees");

return View();
}

The full ExcelLib.cs content:
using ClosedXML.Excel;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;

namespace ExcelGeneratingApp.Models
{
public class ExcelLib
{
// Default Constructor.
public ExcelLib() { }
// Method for adding Header and Title of the table containing List of object values.
public IXLWorksheet addHeader(XLWorkbook wb, List<Object> objs, string title,  string fontFamily = "Sakkal Majalla", string color = "#3498DB")
{
// Sheet initialisation.
var ws = wb.Worksheets.Add("nomDeLaListe").SetTabColor(XLColor.UaBlue);
// font choice.
ws.Style.Font.FontName = fontFamily;
ws.Style.Font.SetFontSize(13);
ws.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
ws.Style.Alignment.WrapText = true;
Object obj = objs.FirstOrDefault();
// Add the model fields to the header of the excel file.
int totalOfFields = obj.GetType().GetProperties().Length; // number of fields in the object.
int numberOfFields = 0;
// Adding the title of table in excel file.
ws.Range(ws.Cell(4, 4), ws.Cell(4, totalOfFields + 3)).Merge().Value = title;
ws.Range(ws.Cell(4, 4), ws.Cell(4, totalOfFields + 3)).Merge().Style.Fill.BackgroundColor = XLColor.FromHtml(color); ;
ws.Range(ws.Cell(4, 4), ws.Cell(4, totalOfFields + 3)).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
ws.Range(ws.Cell(4, 4), ws.Cell(4, totalOfFields + 3)).Style.Font.Bold = true;
ws.Range(ws.Cell(4, 4), ws.Cell(4, totalOfFields + 3)).Style.Font.FontColor = XLColor.WhiteSmoke;
ws.Range(ws.Cell(4, 4), ws.Cell(4, totalOfFields + 3)).Style.Font.FontSize = 18;
//Looping all propeties of the object.
foreach (var prop in obj.GetType().GetProperties())
{
        var displayNameAttribute = prop.GetCustomAttributes(typeof(DisplayNameAttribute), false);
        string displayName = prop.Name;
        if (displayNameAttribute.Count() != 0)
        {
            displayName = (displayNameAttribute[0] as DisplayNameAttribute).DisplayName;
        }
        numberOfFields++;
        ws.Cell(5, totalOfFields - numberOfFields + 4).Value = displayName;
        ws.Cell(5, totalOfFields - numberOfFields + 4).Style.Border.BottomBorder = XLBorderStyleValues.Thin;
        ws.Cell(5, totalOfFields - numberOfFields + 4).Style.Border.LeftBorder = XLBorderStyleValues.Thin;
        ws.Cell(5, totalOfFields - numberOfFields + 4).Style.Border.RightBorder = XLBorderStyleValues.Thin;
        ws.Cell(5, totalOfFields - numberOfFields + 4).Style.Border.TopBorder = XLBorderStyleValues.Thin;
        ws.Column(totalOfFields - numberOfFields + 4).Width = 30;
        ws.Column(totalOfFields - numberOfFields + 4).Style.Font.Bold = true;
}
ws.Range(ws.Cell(5, 4), ws.Cell(5, totalOfFields + 3)).SetAutoFilter();
return ws;
}
public IXLWorksheet addBody(IXLWorksheet ws, List<Object> objs)
{
int numberOfFields = 0;
int numberOfRecords = 0;
Object obj = objs.FirstOrDefault();
int totalOfFields = obj.GetType().GetProperties().Length;
string previousValue = "";
int indexOfPreviousValue = 0;

foreach (var item in objs.ToList())
{
    numberOfFields = 0;
    Type myType = item.GetType();
    IList<PropertyInfo> props = new List<PropertyInfo>(myType.GetProperties());

    foreach (PropertyInfo prop in props)
    {
        object propValue = prop.GetValue(item, null);
        numberOfFields++;
        ws.Cell(6 + numberOfRecords, totalOfFields - numberOfFields + 4).Value = propValue;
        ws.Cell(6 + numberOfRecords, totalOfFields - numberOfFields + 4).Style.Font.Bold = true;
        ws.Cell(6 + numberOfRecords, totalOfFields - numberOfFields + 4).Style.Border.BottomBorder = XLBorderStyleValues.Thin;
        ws.Cell(6 + numberOfRecords, totalOfFields - numberOfFields + 4).Style.Border.LeftBorder = XLBorderStyleValues.Thin;
        ws.Cell(6 + numberOfRecords, totalOfFields - numberOfFields + 4).Style.Border.RightBorder = XLBorderStyleValues.Thin;
        ws.Cell(6 + numberOfRecords, totalOfFields - numberOfFields + 4).Style.Border.TopBorder = XLBorderStyleValues.Thin;

        if (numberOfFields == 1 && numberOfRecords == 0)
        {
            previousValue = propValue.ToString();
        }
        else
        {
            if (numberOfFields == 1)
            {
                if (previousValue == propValue.ToString())
                {
                    ws.Range(ws.Cell(6 + numberOfRecords - (1 + indexOfPreviousValue), totalOfFields - numberOfFields + 4), ws.Cell(6 + numberOfRecords, totalOfFields - numberOfFields + 4)).Merge().Value = propValue.ToString();

                    ws.Range(ws.Cell(6 + numberOfRecords - (1 + indexOfPreviousValue), totalOfFields - numberOfFields + 4), ws.Cell(6 + numberOfRecords, totalOfFields - numberOfFields + 4)).Merge().Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
                    ws.Range(ws.Cell(6 + numberOfRecords - (1 + indexOfPreviousValue), totalOfFields - numberOfFields + 4), ws.Cell(6 + numberOfRecords, totalOfFields - numberOfFields + 4)).Merge().Style.Alignment.Vertical = XLAlignmentVerticalValues.Center;
                    indexOfPreviousValue++;
                }
                else
                {
                    previousValue = propValue.ToString();
                    indexOfPreviousValue = 0;
                }
            }
        }
    }
    numberOfRecords++;
}
return ws;
}
public void Generate(List<Object> objs, string title, string fontFamily = "Sakkal Majalla", string color = "#3498DB")
{
// Workbook creation.
using (XLWorkbook wb = new XLWorkbook())
{
        var ws = addHeader(wb, objs, title);
            ws = addBody(ws, objs);
            wb.SaveAs("C://TestExcelGen.xlsx");
}
}
}
}

NB: You can download all project source code from my github page.

Conclusion
I think the procedure is very clear with snapshots. If you have found any mistake in concept, please do comment. Your comments will make me perfect in the future.
Thanks for reading.

 



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