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 :: 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 :: 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.

 



ASP.NET MVC Hosting - HostForLIFEASP.NET :: Pass Data Across Views In .NET MVC

clock September 30, 2022 09:46 by author Peter

In this article, we will discuss something new: pass data across views. We will also summarize some common or important shared features for various vew variables.

Brief Summary of ViewData
We will start our discussion from ViewData, but most or all features are the same for other MVC View Variables. The ASP.NET Core also has the same features. So, we will discuss ViewData in the most, and have the last part to see the extension to other View variables.


Type of ViewData
We have discussed ViewData, ViewBag, TempData, Session type features. They are all the Type of Dictionary:

Where the difference between ViewBag and ViewData:

Besides ViewBag, all other View Variables need to be cast before using. We define a ViewData named "book": as type BookModel with data such as Id = 1:


When we retrieve data, we have to cast the data back to the data type. Otherwise, we will get an error message:

After casting:

Pass Data into _Layout.cshtml Page by ViewData
The _layout.cshtml is a shared page by other specific views. It belongs to no Controller or Action, or we can say it belongs to every Controller or Action when the related view is using _layout.cshtml. Therefore, we can pass data into Layout either from the Controller or Action view, that uses the _layout.cshtml, such as, if we have a Contact Us Action:

Or, we can define the ViewData from the Contact Us View:

Both ways will pass the data into Layout page:

Notes
1, We usually introduce the Layout into View by the code in the View as below:

2, in some cases, if we want to make the Layout page(s) dynamic, we can assign the layout to the view through Controller/Action:

3, A related important shared concept for MVC, _Viewstat.cshtml


Pass Data into _Layout.cshtml Page by Other View Variables
The same is true for other MVC View Variables, such as ViewBag, TempData, and absolutely Session variable:


Pass TempData to Layout:

Pass ViewData to Layout:

Pass ViewBag to Layout:

This article discussed using ASP.NET MVC ViewData to pass data into Layout View through either Controller or View.  The features are available or the same as other View Variables in ASP.NET MVC, and the same is true for ASP.NET Core MVC.



ASP.NET MVC 6 Hosting - HostForLIFEASP.NET :: Data Sharing Techniques In MVC

clock August 29, 2022 08:55 by author Peter

1) View Data

ViewData is a built-in object of the "ViewDataDictionary" class.
ViewData stores the data in key-value pairs

Example
public IActionResult Index() {
    ViewData["Name"] = "MVC";
    return View();
}


Output

2) View Bag
ViewBag is also used for sending Data from the controller to View.
ViewBag is developed based on Dynamic Typing.
No need to perform Type Casting
Use key as property

Example
public IActionResult ViewBagIndex() {
    ViewBag.Name = "MVC";
    return View();
}


Output


3) Temp Data
TempData is used to transfer the aata from one Action to Another Action at the time of redirection
TempData is an object of the "TempDataDictionary" class

Example
public ActionResult TempDataIndex() {
    TempData["Name"] = "MVC";
    return View();
}

Output

Please do leave a comment if you find it useful.



ASP.NET MVC Hosting - HostForLIFEASP.NET :: How To Generate QR Code In ASP.NET MVC Core 6?

clock July 11, 2022 07:44 by author Peter

In this article, we will learn how to generate QR codes in ASP.NET MVC Core 6 by simply entering Text, numbers, and a combination of both in the textbox and clicking on generate QR code button. I found a very useful library for generating QR codes which are IronBarcode. Download code and play with it.


You can install it through the NuGet package. It supports .Net Core, Standard & Framework. It has cross-platform support.

To use this library we will create a demo project in Visual Studio. I am creating ASP.NET Core Web App (Model-View-Controller). I am going to use the Visual Studio 2022 version.
Creating a New Project in Visual Studio

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 Configure your new project dialog, enter GenerateQRCode_Demo for the Project name. It's important to name the project GenerateQRCode_Demo. 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, and in this example, we are using ASP.Net MVC So we can create a controller to write the code or we can use the existing controller where you can enter the code and build/run the application.

Next, we can add the library to test the code.

How to Install the Barcode 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 IronBarcode using the search box on the upper left. Select a package from the list to display its information, enabling the Install button and a version-selection drop-down. As shown below screenshot. The NuGet package will be installed for your project and reference will be added. As 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.
Using the Visual Studio Command-Line

In Visual Studio, go to Tools-> Nuget Package Manager -> Package Manager Console

Enter the following line in the package manager console tab:

Install-Package IronBarCode

Now the package will download/install to the current project and be ready to use.

Add a class in the Models folder and write or copy-paste the below code.
using System.ComponentModel.DataAnnotations;
namespace GenerateQRCode_Demo.Models {
    public class GenerateQRCodeModel {
        [Display(Name = "Enter QR Code Text")]
        public string QRCodeText {
            get;
            set;
        }
    }
}


We will use exiting HomeController to write the code.
using GenerateQRCode_Demo.Models;
using IronBarCode;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using System.Drawing;
namespace GenerateQRCode_Demo.Controllers {
    public class HomeController: Controller {
        private readonly IWebHostEnvironment _environment;
        public HomeController(IWebHostEnvironment environment) {
            _environment = environment;
        }
        public IActionResult CreateQRCode() {
                return View();
            }
            [HttpPost]
        public IActionResult CreateQRCode(GenerateQRCodeModel generateQRCode) {
            try {
                GeneratedBarcode barcode = QRCodeWriter.CreateQrCode(generateQRCode.QRCodeText, 200);
                barcode.AddBarcodeValueTextBelowBarcode();
                // Styling a QR code and adding annotation text
                barcode.SetMargins(10);
                barcode.ChangeBarCodeColor(Color.BlueViolet);
                string path = Path.Combine(_environment.WebRootPath, "GeneratedQRCode");
                if (!Directory.Exists(path)) {
                    Directory.CreateDirectory(path);
                }
                string filePath = Path.Combine(_environment.WebRootPath, "GeneratedQRCode/qrcode.png");
                barcode.SaveAsPng(filePath);
                string fileName = Path.GetFileName(filePath);
                string imageUrl = $ "{this.Request.Scheme}://{this.Request.Host}{this.Request.PathBase}" + "/GeneratedQRCode/" + fileName;
                ViewBag.QrCodeUri = imageUrl;
            } catch (Exception) {
                throw;
            }
            return View();
        }
    }
}


Next "Add View" right-click on the CreateQRCode action method in HomeController class. Select "Add View" then select "Razor View" next click on the "Add" button.

    In the View name CreateQRCode default name as action method in HomeController.

    Template "Create"

    In the Model, class drop-down, select GenerateQRCodeModel(GenerateQRCodeModel_Demo.Models).

    Select Add.

Following is the CreateQRCode View code.
@model GenerateQRCode_Demo.Models.GenerateQRCodeModel

@{
    ViewData["Title"] = "CreateQRCode";
}
<h1>CreateQRCode</h1>
<div class="row">
  <div class="col-md-4">
    <form asp-action="CreateQRCode">
      <div asp-validation-summary="ModelOnly" class="text-danger"></div>
      <div class="form-group">
        <label asp-for="QRCodeText" class="control-label"></label>
        <input asp-for="QRCodeText" class="form-control" />
        <span asp-validation-for="QRCodeText" class="text-danger"></span>
      </div>
      <div class="form-group">
        <input type="submit" value="Generate QR Code" class="btn btn-primary" />
      </div>
      <div class="form-group">
        <img src="@ViewBag.QrCodeUri" class="img-thumbnail" />
      </div>
    </form>
  </div>
</div>
@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Run project Ctrl+F5


Finally, we can create QR codes using the IronBarcode library. We can save QR codes as jpg, png images, Pdf, or HTML files. We can also add a logo to our QR code file. With its high-performance levels and a vast range of capabilities available to developers working with the Portable Document Format, we prefer IronBarcode.



ASP.NET MVC Hosting - HostForLIFEASP.NET :: How To Create ASP.NET Core MVC 6.0 Application?

clock February 21, 2022 08:46 by author Peter

Prerequisites
    Install Visual Studio 2022 updated version 17.0 or later.
    Install .NET SDK 6.0

Now let's start creating an ASP.NET Core MVC 6.0 web application.

Step 1 - Install Visual Studio
First, install Visual Studio 2022 in your system.

Step 2 - Open Visual Studio
Open Visual Studio 2022.

 

Step 3
Then click on Continue Without Code as shown in the following image


Step 4
Then from Visual Studio Menu, click on File -> New-> Project, as shown in the following image

Click on the New Project, then the following window appears as shown in step 5.

Step 5- Choose Project Template
You can see various project template types, choose the ASP.NET Core Web App (Model-View-Controller) .this project template creates the web application with Model, View and Controller (MVC), as shown in the following image.

After choosing the project template click on Next

Step 6 - Define Project Name and Location
In the project configuration window you will see the following options,

    Project Name
    Define any name for your project as per your choice. Here I have chosen project name as “Asp.NetCore6Demo”.

    Location
    Choose the location to save the project files on your hard drive of the system. I have chosen the Project/VS folder of the E drive of the system.

     Solution Name
    Solution name is auto-defined based on the project name, but you can change the name based on your own choice. But I have not changed my solution name. Solution name and project name both are same.

Additionally, there is a checkbox, if you have checked it, then the solution file (.Soln) and project files will be saved in the same folder. As shown in the following image.


After defining the required details, click on Next.

 Step 7 - Choose the Target Framework

Choose the target framework .NET 6.0 (Long-term support) which is the latest as shown in the following image.


After providing the required details, click the create button. It will create the ASP.NET Core MVC 6.0 web application as shown in step 8.

Step 8 - ASP.NET Core MVC 6.0 Folder Structure
The following is the default folder structure of the ASP.NET Core MVC 6.0 application.


Step 9 - Run the ASP.NET Core MVC 6.0 Application
You can build and run the application with default contents or let open the Index.cshtml file and put some contents there. Here I have some changes in index page.
Now press F5 on the keyboard or use the run option from Visual Studio to run the application in the browser. After running the application, it will show in the browser.

I hope, you have learned how to create the ASP.NET Core MVC 6.0 Web Application.

In this article, we explained how to create ASP.NET Core MVC 6.0 application. I hope this article is useful and easy to understand.



ASP.NET MVC Hosting - HostForLIFEASP.NET :: URL Creation Fundamentals In MVC

clock November 8, 2021 06:49 by author Peter

In this article, we are going to explore different ways of URL creation in MVC and different fundamental concepts of MVC. So let's get started with MVC fundamentals. We have two different approaches available while creating an URL in MVC framework.
    ActionLink
    Raw HTML

Action LInk in the background queries the routing engine whenever the URL associated with the given controllers ACTION. Sometimes we do have Custom URLs associated with an action, and we require to change that URL in future. For this scenario actionLink will pick up the latest URL, you don't need to make any changes.

On the other hand, if you are using raw HTML, you need to update your links when URLs changed.

As a good programmer, we should always avoid changing URLs as URLs are the public contract of your app and can be referenced by other apps, and many times users bookmark the URLs. If you change them, all these bookmarks and references will be broken.

In the end, the decision is up to the programmer's choice, no hard and fast rule here.

Again, the simplest way is using raw HTML

1: Raw HTML
Example,
<a href = "Courses/Index"> View Course</a>

2: ActionLink
Below is the example of using ActionLink for URL creation.
@HTML.ActionLink("View Courses","Index","Courses")

If the targeted action needs a parameter we can make use of an anonymous object to pass the parameter values.
@HTML.ActionLink("View Courses","Index","Courses", new {id = 1})

This will generate a link as - courses/index/1

This method doesn't generate the link for a reason, we need to pass another argument to ActionLink. This argument can be null or an anonymous object to render any additional HTML attribute.
@HTML.ActionLink("View Courses","Index","Courses", new {id = 1}, null)

We have different HTML helpers available in MVC 

Type Helper Method
ViewResult View()
PartialViewResult PartialView()
RedirectResult Redirect()
ContentResult Content()
JsonResult Json()
RedirectToRouteResult RedirectToAction()
FileResult File()
HttpNotFoundResult HttpNotFound()
EmptyResult  

Passing Data to views in MVC
We should avoid passing data using ViewData and ViewBag as these methods are fragile and need a lot of casting which makes code ugly. Instead, we can pass model or viewModel directly to view.
return View(Course);

Razor Views
@if(condition)
{
    // c# or HTML code
}


@foreach(...)
{
}


We can render a class or any attribute conditionally as follows,
@{
    var className=Model.Movies.Count >3 ? "Popular" : null;
}
<h2 class = "@className">...</h2>

Partial View

@Html.Partial("_NavBar")

Types of Routing in MVC
1: Convention based Routing

Here we can specify the routing in RouteConfig.cs file and mention the Controller, action which needs to be invoked using mapRoute method of routes collection.

2: Attribute based Routing

Here we can apply route by decorating the action method with the Route keyword followed by the path.

Authentication in MVC
Use [authorize] keyword. Apply it to action, controller or globally (in FilterConfig.cs)
Enabling Social Login in MVC

Step 1
Enable SSL: Select project, press F4, set SSL enabled to true.

Step 2
Copy SSL URL, select the project, go to properties, in the Web tab, set startup URL.

Step 3
Apply RequireSSL filter globally in FilterConfig.cs file.

Step 4
Register your app with external authentication providers to get secret key/secret. In AppStart.cs/Startup.Auth.cs, add corresponding providers and your key/secret.
Summary

In this article, we explored different ways of URL creation in MVC and different fundamental concepts of MVC. I hope you liked the article. Until Next Time - Happy Learning Cheers



ASP.NET MVC 6 Hosting - HostForLIFEASP.NET :: Output Caching in MVC

clock June 16, 2021 09:09 by author Peter

The main purpose of using Output Caching is to dramatically improve the performance of an ASP.NET MVC Application. It enables us to cache the content returned by any controller method so that the same content does not need to be generated each time the same controller method is invoked. Output Caching has huge advantages, such as it reduces server round trips, reduces database server round trips, reduces network traffic etc.

 
Keep the following in mind:
    Avoid caching contents that are unique per user.

    Avoid caching contents that are accessed rarely.

    Use caching for contents that are accessed frequently.

Let's take an example. My MVC application displays a list of database records on the view page so by default each time the user invokes the controller method to see records, the application loops through the entire process and executes the database query. And this can actually decrease the application performance. So, we can advantage of the "Output Caching" that avoids executing database queries each time the user invokes the controller method. Here the view page is retrieved from the cache instead of invoking the controller method and doing redundant work.
Cached Content Locations
 
In the above paragraph I said, in Output Caching the view page is retrieved from the cache, so where is the content cached/stored?
 
Please note, there is no guarantee that content will be cached for the amount of time that we specify. When memory resources become low, the cache starts evicting content automatically.
 
OutputCache label has a "Location" attribute and it is fully controllable. Its default value is "Any", however there are the following locations available; as of now, we can use any one.
 
1. Any   2. Client   3. Downstream   4. Server   5. None   6. ServerAndClient
 
With "Any", the output cache is stored on the server where the request was processed. The recommended store cache is always on the server very carefully. You will learn about some security related tips in the following "Don't use Output Cache".
 
How Output Cache Works
It is very important to understand how the "Output Cache" works. Anyone who invokes a controller method will get the same cached version of the view page. This means that the amount of work that the web server must perform to serve the view page is dramatically reduced.
 
For example, I have recorded a GIF here to show you how the same request is being made from three different clients (here three different browsers) and we are getting the same cached version (look at the time).

Okay, now let's look at the code, how I developed the one above, how to make any controller action or method cacheable. Here it is
[OutputCache(Duration = 10, VaryByParam = "name")]
 
Just add the preceding label before the controller method. The duration is in seconds, 10 seconds here. If you don't provide a "Duration" value then the default will be used, 60 seconds. I am using VaryByParam="name" and "VeryByParam" is something that makes many differences that you should care about that will be discussed later. "name" is a parameter passed by the user with the request to do database records filering.
 
Here is the complete code:
    [HttpPost]  
        [OutputCache(Duration = 10, VaryByParam = "name")]  
        public ActionResult SearchCustomer(string name = "")  
        {  
            NorthwindEntities db = new NorthwindEntities();  
            var model = from r in db.Customers  
                        where r.ContactName.Contains(name)  
                        select r;  
            if (model.Count() > 0)  
            {  
                return View(model);  
            }  
            else  
            {  
                return View();  
            }  
        }  


In the code above, I'm looking at the "name" parameter passed by the user and then, depending on the name, selecting matching records with a LINQ query and then checking if the model has the number of records greater than zero then send the model to the view else simply send the view (no model).
VaryByParam can be one of the following types:

1. VaryByParam = "none": Think of it like, we don't want to care about the form parameter or query string parameter passed by the user from the view page. If I use "none" then it will create the same cached version of the content for every user who visits the website, and the content will only change after a specified number of seconds (here 10 seconds).

Let's use [OutputCache(Duration = 10, VaryByParam = "none")] in the code above and look at the behavior.

In above GIF you can notice on second request to see list of records that contains "a" nothing happens, because it is displaying the cached data.
2. VaryByParam = "name": This property enables you to create different cached versions of the content when a form parameter or query string parameter varies. In other words if I find records matching "ce" string then a new cache will be created by replacing the older one, again if I find records matching "ab" string then a new cache will be created by replacing the last one ("ce" cached), no matter duration is elapsed or not.
 
Let's use [OutputCache(Duration = 10, VaryByParam = "name")] in code above and look at behavior.

In the above GIF note that on each new request with a different query string parameter or form parameter, a new cache is being created; look at the time it is changing. Here the use of the cache is that if I request the same thing that I requested previously then the cached version will be rendered, here it is:

In the above GIF note that nothing happens (look at the time) when I continuously request the same information, rendering the cached version.
3. VaryByParam = "*": We can use * for all parameters or a semi-colon separated list to cache various versions. This works very similar to the one above (VaryByParam="name").
    [OutputCache(Duration = 10, VaryByParam = "*")]  
    public ActionResult SearchCustomer(string name = "", string city = "")  
    {  
        NorthwindEntities db = new NorthwindEntities();  
        ...  

OR
    [OutputCache(Duration = 10, VaryByParam = "name; city")]  
    public ActionResult SearchCustomer(string name = "", string city = "")  
    {  
        NorthwindEntities db = new NorthwindEntities();  
        ...  

Both scenarios work the same, so use whichever one that makes you happy.
Check Web Page is Cache-able or not?
 
Fiddler is a great tool if you want to check whether a requested web page is cache-able or not, here is a GIF image of it.

In the above GIF you can see the GET request is not cacheable whereas the POST request is cacheable and with max-age: 10 seconds.
Don't use Output Cache
 
Here you will learn about some quick security related issues and their prevention.

Danger 1
We should always be careful while using "OutputCache", I will show you an example here. Let's look at the following controller action method and try finding security vulnerabilities.
    [OutputCache(Duration = 10, VaryByParam = "none")]  
        public ActionResult Profiles()  
        {  
            if (User.Identity.IsAuthenticated)  
            {  
                MembershipUser u = Membership.GetUser(User.Identity.Name);  
                ViewBag.welcomeNote = "Welcome back " + User.Identity.Name + ". Your last login date was " + u.LastLoginDate;  
            }  
            else  
            {  
                ViewBag.welcomeNote = "Welcome Guest";  
            }  
            return View();  
        }  
       


Now, I'm running the code above, see how the usernames are appearing in both (IE and Chrome) browsers, the GIF is given below. Username is also being cached and stored on the server for other users.

In the above controller action method we don't have a "VaryByCustom" or "Location" attribute with "OutputCache" to safeguard it, so by default it uses Location = OutputCacheLocation.Any that is dangerous in this case. If you are using membership in the web application then you should pay special attention. A few ways are given below, the first is more secure and recommendable.

1st Way
You can also take advantage of the VaryByCustom property in [OutputCache] by overriding HttpApplication.GetVaryByCustomString and checking HttpContext.Current.User.IsAuthenticated.

This is what I will create in the Global.asax.cs file:
    public override string GetVaryByCustomString(HttpContext context, string custom)  
    {  
        if (custom == "LoggedUserName")  
        {  
            if (context.Request.IsAuthenticated)  
            {  
                return context.User.Identity.Name;  
            }  
            return null;  
        }  
        return base.GetVaryByCustomString(context, custom);  
    }  


And then use it in the OutputCache attribute:
    [OutputCache(Duration = 10, VaryByParam = "none", VaryByCustom = "LoggedUserName")]  
    public ActionResult Profiles()  
    {  
        //...  
    }  

Now for every user logged in on the website OutputCache will create a separate version, and it works great. We can even use Duration, VaryByParam, VaryByCustom and Location attributes together to make it more productive, useful and secure.

We can also enable separate cache entries for each browser, VaryByCustom can be set to a value of "browser". This functionality is built into the caching module, and will insert separate cached versions of the page for each browser name and major version. You don't need to override HttpApplication.GetVaryByCustomString.
    [OutputCache(Duration = 10, VaryByParam = "none", VaryByCustom = "browser")]  
    public ActionResult Profiles()  
    {  
       ...  


2nd Way
See, this is less reliable but works. You should use Location = OutputCacheLocation.Client. If you don't, the login username will also be cached and stored on the server for other users and that is confusing & quite dangerous.

Here is the complete controller action method code.
    [OutputCache(Duration = 10, VaryByParam = "none", Location = OutputCacheLocation.Client)]  
    public ActionResult Profiles()  
    {  
        ...  
    }  

Note 1: POST requests are not cached on the client, in other words this will not work because it is a POST request and the caching location is on the client.
      [HttpPost]  
    [OutputCache(Duration = 10, VaryByParam = "name", Location = OutputCacheLocation.Client)]  
    public ActionResult SearchCustomer(string name = "")  
    {  
        ...  
    }  


Note 2: If you are trying to test client-side caching (like the one given above) and hitting F5 then you are losing the client cache. The way the client cache is supposed to work is that you have links on the site pointing to the Client action from some other views and when the user clicks on those links the cached version will be served.

Danger 2
If you want a more secure application then you should only enable caching for a page when the page does not require authorization. Normally, you require authorization for a page when you display personalized data in the page. Since you don't want personalized data to be shared among multiple users, don't cache pages that require authorization.
    [Authorize]  
    [OutputCache(Duration = 10, VaryByParam = "none")]  
    public ActionResult CreditCardDetails()  
    {  
        ...  
    }  


In the code above, you are combining OutputCaching and Authorize with an action method that contains your credit card information. And you know how OutputCaching stores data out of the database that is not as secure as a database. So you are broadcasting your private information to the entire world. Don't do it.

Creating Cache Profile
It is very difficult to change the rules (like Duration, VaryByParam, VaryByCustom, Location) used with "OutputCache" on each controller method when your large application has already been deployed.

So, there is an alternative to configure the OutputCache profile in the web.config file. By configuring output caching in the web configuration file, you can control it on one central location. You can create one cache profile and apply the profile to several controllers or controller actions. Also, you can modify the web configuration file without recompiling your application. Any changes to the web configuration file will be detected automatically and applied to the entire application.

In the following code you can see I have used a new attribute CacheProfile that maps to Cache10Seconds that is in web.config.
    [OutputCache(CacheProfile = "Cache10Seconds", VaryByCustom = "LoggedUserName")]  
    public ActionResult Profiles()  
    {  
       ...  

And then web.config:
    <system.web>  
      <caching>  
        <outputCacheSettings>  
            <outputCacheProfiles>  
                <add name="Cache10Seconds" duration="10" varyByParam="none"/>  
            </outputCacheProfiles>  
        </outputCacheSettings>  
      </caching>  
      ...  


Please note, I moved Duration, VaryByParam and Location (we can use it also) in web.config but not VaryByCustom and the reason is, it is used for overriding the rules.
Now, assume for any reason I want to disable caching for an entire application that has already been deployed to production, then you can simply modify the cache profiles defined in the web configuration file.
 
We can even disable it as in the following:

    <system.web>  
        <caching>  
            <outputCache enableOutputCache="false" =""/>  
            <outputCacheSettings>  
                  <outputCacheProfiles>  
                        <add name="Cache10Seconds" duration="10" varyByParam="none"/>                 
          </outputCacheProfiles>           
        </outputCacheSettings>  
      </caching>  

This approach is pretty good because rather than targeting any specific outputCacheProfile we can disable all at once, awesome.



ASP.NET MVC 6 Hosting - HostForLIFEASP.NET :: Create Simple Web API In ASP.NET MVC

clock March 26, 2021 08:32 by author Peter

This article explains how to access data from a view to the controller's action method. The action method is a simple C# method that can be parameterized or without a parameter in the controller. We use two types of methods to handle our browser request; one is HTTP GET and another is HTTP POST. When we call an action method by a request's URL by the browser then the HTTP GET method will be called but when a request is from a button click event then the HTTP POST method will be called. So in this article, I am going to explaining how to access view input field data in the controller's action method when a HTTP POST request is called.

 
To understand how to access view input field data in the controller's action method (POST), we create a "Calculate Simple Interest" application. This application gets Principle, Rate and Time as user input and generates simple interest. So let's proceed with the application.
 
Create an action method in the CalculateSimpleInterest controller (CalculateSimpleInterestController.cs) that renders the view on the UI.
    public ActionResult SimpleInterest()  
    {  
        return View();  
    }  

Create a view to get user input from the UI, so the code is:
    <h2>Calculate Simple Interest</h2>  
    <fieldset>  
            <legend>Calculate Simple Interest</legend>  
        @using (Ajax.BeginForm("CalculateSimpleInterestResult","CalculateSimpleInterest",  
                                new AjaxOptions { UpdateTargetId = "divInterestDeatils" }))  
        {  
            <div id="divInterestDeatils"></div>  
            <ol>  
                <li>  
                    @Html.Label("Amount")  
                    @Html.TextBox("txtAmount")  
                </li>  
                <li>  
                    @Html.Label("Rate")  
                    @Html.TextBox("txtRate")  
                </li>  
                <li>  
                    @Html.Label("Year")  
                    @Html.TextBox("txtYear")  
                </li>  
            </ol>  
        <button>Calculate</button>  
        }     
    </fieldset>  


So now the screen is ready to get input and it shows it as:

 

Figure 1.1 Input screens to calculate simple interest

I will now explain the four ways to get the view's data in the controller action. These are:
    Using Traditional approach
    Using the FormCollection Object
    Using the Parameters
    Strongly type model binding to view

Using Traditional Approach
In the traditional approach we use the request object of the HttpRequestBase class. The request object has view input field values in name/value pairs. When we create a submit button then the request type POST is created and calls the POST method.

Figure 1.2 Requested Data

We have four data, those are in Name-Value pairs. So we can access these data in a POST method by passing the Name as an indexer in the Request and get values. Our POST method means the controller action that handles the POST request type is [HttpPost].
    [HttpPost]  
    public ActionResult CalculateSimpleInterestResult()  
    {  
        decimal principle = Convert.ToDecimal(Request["txtAmount"].ToString());  
        decimal rate = Convert.ToDecimal(Request["txtRate"].ToString());  
        int time = Convert.ToInt32(Request["txtYear"].ToString());  
       
        decimal simpleInteresrt = (principle*time*rate)/100;  
       
        StringBuilder sbInterest = new StringBuilder();  
        sbInterest.Append("<b>Amount :</b> " + principle+"<br/>");  
        sbInterest.Append("<b>Rate :</b> " + rate + "<br/>");  
        sbInterest.Append("<b>Time(year) :</b> " + time + "<br/>");  
        sbInterest.Append("<b>Interest :</b> " + simpleInteresrt);  
        return Content(sbInterest.ToString());  
    }  


When it executes, we get simple interest as the result as in the following:

Figure 1.3 Output screen after getting response

Using the FormCollection Object
We can also get post requested data by the FormCollection object. The FormCollection object also has requested data in the name/value collection as the Request object. To get data from the FormCollection object we need to pass it is as a parameter and it has all the input field data submitted on the form.
    [HttpPost]  
      
    public ActionResult CalculateSimpleInterestResult(FormCollection form)  
    {  
        decimal principle = Convert.ToDecimal(form["txtAmount"].ToString());  
        decimal rate = Convert.ToDecimal(form["txtRate"].ToString());  
        int time = Convert.ToInt32(form["txtYear"].ToString());  
       
        decimal simpleInteresrt = (principle*time*rate)/100;  
       
        StringBuilder sbInterest = new StringBuilder();  
        sbInterest.Append("<b>Amount :</b> " + principle+"<br/>");  
        sbInterest.Append("<b>Rate :</b> " + rate + "<br/>");  
        sbInterest.Append("<b>Time(year) :</b> " + time + "<br/>");  
        sbInterest.Append("<b>Interest :</b> " + simpleInteresrt);  
        return Content(sbInterest.ToString());  
    }


It also gives the same output as Figure 1.3 shows.
 
Using the Parameters

We can pass all input field names as a parameter to the post action method. The input field name and parameter name should be the same. These parameters have input field values that were entered by the user. So we can access view input field values from these parameters. The input field takes a string value from the user so the parameter should be a string type. There is no need to define a parameter in any specific sequence.
    [HttpPost]  
    public ActionResult CalculateSimpleInterestResult(string txtAmount, string txtRate, string txtYear)  
    {  
        decimal principle = Convert.ToDecimal(txtAmount);  
        decimal rate = Convert.ToDecimal(txtRate);  
        int time = Convert.ToInt32(txtYear);  
       
        decimal simpleInteresrt = (principle*time*rate)/100;  
       
        StringBuilder sbInterest = new StringBuilder();  
        sbInterest.Append("<b>Amount :</b> " + principle+"<br/>");  
        sbInterest.Append("<b>Rate :</b> " + rate + "<br/>");  
        sbInterest.Append("<b>Time(year) :</b> " + time + "<br/>");  
        sbInterest.Append("<b>Interest :</b> " + simpleInteresrt);  
        return Content(sbInterest.ToString());  
    }  


It also gives the same output as Figure 1.3 shows.
 
In all three approaches above we are parsing the string to a non-string type. If any of the parsing attempts fail then the entire action will fail. We are converting each value to avoid an exception but it also increases the amount of code. So we look at the fourth approach that would reduce the amount of code.
 
Strongly type model binding to view
 
We bind a model to the view; that is called strongly type model binding.
 
Step 1
Create a Model for Simple Interest
    namespace CalculateSimpleInterest.Models  
    {  
        public class SimpleInterestModel  
        {  
            public decimal Amount { get; set; }  
            public decimal Rate { get; set; }  
            public int Year { get; set; }  
        }  
    }  


Step 2
Create an action method that render a view on the UI
 
We are passing an empty model to be bound to the view.
    public ActionResult SimpleInterest()  
    {  
        SimpleInterestModel model = new SimpleInterestModel();  
        return View(model);  
    }  


Step 3
Create a strongly typed view that has the same screen as in Figure 1.1
    @model CalculateSimpleInterest.Models.SimpleInterestModel  
       
    @{  
        ViewBag.Title = "SimpleInterest";  
    }  
       
    <h2>Calulate Simple Interest</h2>  
       
    @using (Ajax.BeginForm("CalculateSimpleInterestResult","CalculateSimpleInterest",  
                                new AjaxOptions { UpdateTargetId = "divInterestDeatils" }))  
        {  
             
        <fieldset>  
            <legend>Calulate Simple Interest</legend>  
            <div id="divInterestDeatils"></div>  
       
            <div class="editor-label">  
                @Html.LabelFor(model => model.Amount)  
            </div>  
            <div class="editor-field">  
                @Html.EditorFor(model => model.Amount)            
            </div>  
       
            <div class="editor-label">  
                @Html.LabelFor(model => model.Rate)  
            </div>  
            <div class="editor-field">  
                @Html.EditorFor(model => model.Rate)            
            </div>  
       
            <div class="editor-label">  
                @Html.LabelFor(model => model.Year)  
            </div>  
            <div class="editor-field">  
                @Html.EditorFor(model => model.Year)             
            </div>  
            <p>  
                <input type="submit" value="Calculate" />  
            </p>  
        </fieldset>  
    }  
       
    @section Scripts {  
        @Scripts.Render("~/bundles/jqueryval")  
    }  

Step 4
Create an action method that handles the POST request and processes the data
 
In the action method we pass a model as the parameter. That model has UI input field data. Here we do not need to parse and do not need to write extra code.
    [HttpPost]  
    public ActionResult CalculateSimpleInterestResult(SimpleInterestModel model)  
    {  
        decimal simpleInteresrt = (model.Amount*model.Year*model.Rate)/100;  
        StringBuilder sbInterest = new StringBuilder();  
        sbInterest.Append("<b>Amount :</b> " + model.Amount+"<br/>");  
        sbInterest.Append("<b>Rate :</b> " + model.Rate + "<br/>");  
        sbInterest.Append("<b>Time(year) :</b> " + model.Year + "<br/>");  
        sbInterest.Append("<b>Interest :</b> " + simpleInteresrt);  
        return Content(sbInterest.ToString());  
    }  

It also gives the same output as Figure 1.3 shows.



ASP.NET MVC 6 Hosting - HostForLIFEASP.NET :: HTTP Error 404.0 0 Not Found in MVC

clock January 29, 2021 08:32 by author Peter

The Resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
I saw this error today while working on a MVC Web Project, this is a common error we get while running websites and performing any CRUD (Create, Read, Update, Delete) operation. The Stackoverflow forum is full of such queries so I decided to describe the fix here. You might not find it useful for your case but I think the majority of requests can be satisfied.

 
Let me show you an error page image here:


Look at the URL in the above image. The URL is requesting a view/page to edit the record but unfortunately the page is not found. Actually the page/view is already there but the problem is, we are not supplying the correct ID or say index to edit.
In other words we need an URL something like http://localhost:25349/demo/Edit/1 to edit the first record and http://localhost:25349/demo/Edit/2 to edit the second record. Yet in the preceding image we are not supplying the ID.
 
Let's fix it. Open the "Index" view of the "demo" controller and look at the existing code:


Oh! there is a comment instead of the ID parameter, so once you change it, such as in the following:
    <td>  
        @Html.ActionLink("Edit", "Edit", new { id=item.SM_UID }) |  
        @Html.ActionLink("Details", "Details", new { id=item.SM_UID }) |  
        @Html.ActionLink("Delete", "Delete", new { id=item.SM_UID })  
    </td>  


Your application will work fine.



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.


Tag cloud

Sign in