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 :: View Injection In ASP.NET Core MVC

clock August 16, 2022 09:15 by author Peter

View injection is the most useful feature introduced in ASP.NET Core. Using ASP.NET Core inbuilt dependency injection container, we can easily inject dependencies in Controllers, Filters, and Views. In this post, I am going to show how to inject dependencies using inject keyword in the View.

Previously, to retrieve the data in View, we needed to pass it from the Controller using Controller properties, like ViewBag, ViewData or model properties. In ASP.NET Core MVC, things are quite smooth by the usage of Inject directive. Inject helps with injecting the dependencies directly to the View and retrieving the data.

Setup project
In Visual Studio, create a new project (File > New > Project), and select ASP.NET Core Web Application (.NET Core).

Enter a name for the application and click OK. Select Web Application to generate the default ASP.NET Core MVC project.

Visual Studio will automatically generate ASP.NET Core MVC project structure and display a welcome screen.

Add Services
Add a new folder "Models" and add FruitServices class in it. Now, add a method GetFruits() which returns List<string>().

    public class FruitServices  
    {  
        public List<string> GetFruits()  
        {  
            return new List<string>() { "Mango", "Apple", "Apricot", "Banana", "Grapes" };  
        }  
    }  


Inject in View
We can inject a service into a View using the @inject directive. You can think of @inject as adding a property to your View, and populating the property using DI.
 
The basic syntax for View Injection is:
    @inject <service> <name>  

    @inject is the directive used to inject dependencies
    <service> is service class.
    <name> is the service injection name by which we can access service methods.


In our example, we are going to inject FruitServices and give service injection name fruitList.
    @inject MVCCoreExample.Models.FruitServices fruitList  
      
    <h3>Fruit List</h3>  
    <ul>  
        @foreach (var name in fruitList.GetFruits())  
        {  
            <li>@name</li>  
        }  
    </ul>  


This View displays a list of fruits which are populated from the injected FruitServices. Using GetFruit() method, we can retrieve a list of fruits.
 
Let's run it without registering FruitServices in DI container.

When we run the app, it will throw an invalid operation exception "No service for type 'MVCCoreExample.Modes.FruitServices' has been registered". This error occurred because we didn't register FruitServices in a dependency injection container.
 
Let's register it first and try again!
Register Service
Open startup.cs class and register service for dependency injection in ConfigureServices method. You can register your own application services, using AddTransient method. FruitServices will be instantiated by the container and used to fulfill such requests.

    public void ConfigureServices(IServiceCollection services)  
    {  
        // Add framework services.  
        services.AddMvc();  
        services.AddTransient<FruitServices>();  
    }  

Run it!
Here it is! The sample displays the data from the service injected in View.

 

Injecting dependencies directly into MVC View can make things a bit easier. In this post, I have shown a simple View Injection sample to understand the use of Inject directive. View injection can be useful for populating UI elements, like selection list, radio buttons etc. This will increase code re-usability and keep your Controller clean by minimizing the amount of code required on Controllers.



ASP.NET MVC Hosting - HostForLIFEASP.NET :: Web API CRUD Operations And Consume Service In ASP.NET MVC Application

clock August 9, 2022 09:00 by author Peter

This article will give you an understanding of the what and the why of Web API and will demonstrate a CRUD operation with a simple example using Entity Framework and consuming the created service into ASP.NET MVC application.

 
The flow of the article

    What is Web API
    Why Web API
    Real time example of WEBAPI
    Steps to Create table, Web API Service, and MVC application to consume the service.

        Create a table in SQL Server.
        Create Data Access Layer in Visual Studio to access the data and perform DB operation.
        Create a Web API project.
        Create MVC Application to consume Web API Service. Project created in step II, III, and IV belonging to one same solution
        Set Project Startup Order

    Output Screens
    Conclusion

Web API
    Web API provides service that can be consumed by a broad range of clients like mobile, tablet, desktop, etc.
    The response can be in any format, like XML, JSON (widely used), etc.
    It supports MVC features, like controller, action, routing, etc.
    Supports CRUD operation. CRUD stands for Create, Read, Update and Delete. It works on HTTP verbs like HttpPost to Create, HttpGet to Read, HttpPut to Update and HttpDelete to Delete.

Why Web API?


Without Web API, the server will have one application to handle the XML request and another application to handle the JSON request, i.e., for each request type, the server will have one application. But with Web API, the server can respond to any request type using a single application. Small end devices like mobile, tablet are capable of handling only the JSON data. So, the Web API has huge scope to give space in the real world.
 
A real-time example of WebAPI

    Weather forecasting
    Movie, Bus, Flight booking

There can be one service provider who offers the service and many consumers to avail this service.
 
Step 1 - Create a table in SQL Server
We will create a table to perform CRUD operation with Web API. The table script is given below.

    CREATE TABLE [dbo].[Product](  
        [ProductId] [int] PRIMARY KEY IDENTITY(1,1) NOT NULL,  
        [ProductName] [nvarchar](100) NULL,  
        [Quantity] [int] NULL,  
        [Price] [int] NULL)  


Step 2 - Create Class Library Project
    New Project -> Visual C# -> Windows -> Class Library Project and name it as DataAccessLayer.
    Right-click on DataAccessLayer project->Add->New Item->Data-> ADO.NET Entity Data Model and name it as ShowRoomEF.
    Choose EF designer from database in next step.
    Add the table created in step1 into Entity Framework.



Create a class called DAL.cs in this project to access the data from DB by Web API service. The code is given below.

DAL.cs
    public static class DAL  
    {  
        static ShowroomEntities DbContext;  
        static DAL()  
        {  
            DbContext = new ShowroomEntities();  
        }  
        public static List<Product> GetAllProducts()  
        {  
            return DbContext.Products.ToList();  
        }  
        public static Product GetProduct(int productId)  
        {  
            return DbContext.Products.Where(p => p.ProductId ==  productId).FirstOrDefault();  
        }  
        public static bool InsertProduct(Product productItem)  
        {  
            bool status;  
            try  
            {  
                DbContext.Products.Add(productItem);  
                DbContext.SaveChanges();  
                status = true;  
            }  
            catch (Exception)  
            {  
                status = false;  
            }  
            return status;  
        }  
        public static bool UpdateProduct(Product productItem)  
        {  
            bool status;  
            try  
            {  
                Product prodItem = DbContext.Products.Where(p => p.ProductId == productItem.ProductId).FirstOrDefault();  
                if (prodItem != null)  
                {  
                    prodItem.ProductName = productItem.ProductName;  
                    prodItem.Quantity = productItem.Quantity;  
                    prodItem.Price = productItem.Price;  
                    DbContext.SaveChanges();  
                }  
                status = true;  
            }  
            catch (Exception)  
            {  
                status = false;  
            }  
            return status;  
        }  
        public static bool DeleteProduct(int id)  
        {  
            bool status;  
            try  
            {  
                Product prodItem = DbContext.Products.Where(p => p.ProductId == id).FirstOrDefault();  
                if (prodItem != null)  
                {  
                    DbContext.Products.Remove(prodItem);  
                    DbContext.SaveChanges();  
                }  
                status = true;  
            }  
            catch (Exception)  
            {  
                status = false;  
            }  
            return status;  
        }  
    }  

Step 3 - Create Empty Web API Project
 
Navigate as given
Select New Project -> Visual C# -> Web -> ASP.NET Web Application and enter your application and solution name.

Select the empty template from options and check Web API checkbox and click OK.

The solution will be created as below.



    In App_Start -> WebApiConfig.cs file make sure routeTemplate as given below because by default, the route will not have {action}.

In WebApiConfig.cs

    public static void Register(HttpConfiguration config)  
           {  
               // Web API configuration and services  
      
               // Web API routes  
               config.MapHttpAttributeRoutes();  
      
               config.Routes.MapHttpRoute(  
                   name: "DefaultApi",  
                   routeTemplate: "api/{controller}/{action}/{id}",  
                   defaults: new { id = RouteParameter.Optional }  
               );  
     }

    Add Reference to DataAccessLayer project.
    Add the below DLL in references.

        EntityFramework
        SqlServer
        Net.Http
        Net.Http.Formatting

    Install Entity Framework from ‘NuGet Package Manager’.
    Create a Model class for the product as below.


Product.cs
    namespace WebApiService.Models  
    {  
        public class Product  
        {  
            public int ProductId { get; set; }  
            public string ProductName { get; set; }  
            public Nullable<int> Quantity { get; set; }  
            public Nullable<int> Price { get; set; }  
        }  
    }  

Copy the connection string from DataAccessLayer -> web.config and paste it in WebApiService -> web.config.
    <connectionStrings>  
        <add name="ShowroomEntities" connectionString="metadata=res://*/ShowRoomEF.csdl|res://*/ShowRoomEF.ssdl|res://*/ShowRoomEF.msl;provider=System.Data.SqlClient;provider connection string="data source=MYSYSTEM\SQLEXPRESS;initial catalog=Showroom;user id=sa;password=xxxxx;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />  
      </connectionStrings>  


Add Showroom Controller and make class to inherit from ApiController.
 
ShowroomController.cs

Showroom Controller takes care of Inserting, Retrieving, Updating and Deleting the data in the database. Request comes to this controller from the consuming application.
    public class ShowroomController: ApiController {  
        // GET: Showroom  
        [HttpGet]  
        public JsonResult < List < Models.Product >> GetAllProducts() {  
                EntityMapper < DataAccessLayer.Product, Models.Product > mapObj = new EntityMapper < DataAccessLayer.Product, Models.Product > ();  
                List < DataAccessLayer.Product > prodList = DAL.GetAllProducts();  
                List < Models.Product > products = new List < Models.Product > ();  
                var config = new MapperConfiguration(cfg => cfg.CreateMap < Product, Models.Product > ());  
                var mapper = new Mapper(config);  
                foreach(var item in prodList) {  
                    products.Add(mapper.Map < Models.Product > (item));  
                }  
                return Json < List < Models.Product >> (products);  
            }  
            [HttpGet]  
        public JsonResult < Models.Product > GetProduct(int id) {  
                EntityMapper < DataAccessLayer.Product, Models.Product > mapObj = new EntityMapper < DataAccessLayer.Product, Models.Product > ();  
                DataAccessLayer.Product dalProduct = DAL.GetProduct(id);  
                Models.Product products = new Models.Product();  
                var config = new MapperConfiguration(cfg => cfg.CreateMap < Product, Models.Product > ());  
                var mapper = new Mapper(config);  
                products = mapper.Map < Models.Product > (dalProduct);  
                return Json < Models.Product > (products);  
            }  
            [HttpPost]  
        public bool InsertProduct(Models.Product product) {  
                bool status = false;  
                if (ModelState.IsValid) {  
                    EntityMapper < Models.Product, DataAccessLayer.Product > mapObj = new EntityMapper < Models.Product, DataAccessLayer.Product > ();  
                    DataAccessLayer.Product productObj = new DataAccessLayer.Product();  
                    var config = new MapperConfiguration(cfg => cfg.CreateMap < Models.Product, Product > ());  
                    var mapper = new Mapper(config);  
                    productObj = mapper.Map < Product > (product);  
                    status = DAL.InsertProduct(productObj);  
                }  
                return status;  
            }  
            [HttpPut]  
        public bool UpdateProduct(Models.Product product) {  
                EntityMapper < Models.Product, DataAccessLayer.Product > mapObj = new EntityMapper < Models.Product, DataAccessLayer.Product > ();  
                DataAccessLayer.Product productObj = new DataAccessLayer.Product();  
                var config = new MapperConfiguration(cfg => cfg.CreateMap < Models.Product, Product > ());  
                var mapper = new Mapper(config);  
                productObj = mapper.Map < Product > (product);  
                var status = DAL.UpdateProduct(productObj);  
                return status;  
            }  
            [HttpDelete]  
        public bool DeleteProduct(int id) {  
            var status = DAL.DeleteProduct(id);  
            return status;  
        }  
    }  


Check your service
Execute your service created just now by running the below URL in the browser and change the port number accordingly.
http://localhost:52956/api/showroom/getallproducts
 

Service Output

Note
Attached WebApiServiceProvider.zip solution.
since solution size exceeds permitted one, have removed 'packages' folder content of 'WebApiServiceProvider' and kept in package_content_1.zip and package_content_2.zip.
 
Kindly don't forget to unzip package_content_1.zip and package_content_2.zip and keep their contents in 'WebApiServiceProvider\packages' folder. Also make changes to connection strings accordingly in both the solution.
 
Step 4 – Consuming Web Api Service In MVC Application
    Create Empty MVC project as below.



Create Product model class as created in WebApiService project.
Create ServiceRepository.cs in Repository folder to consume the web api service and create ServiceUrl as key and as a value in web.config (port number changes according to the server).
    <add key="ServiceUrl" value="http://localhost:52956/"></add>  

Add the below DLL in the references.
    Net
    Net.Http
    Net.Http.Formatting

ServiceRepository.cs
Service Repository is created to act as a reusable module for requesting, posting, updating and deleting data in WebAPI. This is used by any action method in the Controller which is created in next step and avoids duplication of this code.

public class ServiceRepository  
{  
       public HttpClient Client { get; set; }  
       public ServiceRepository()  
       {  
           Client = new HttpClient();  
           Client.BaseAddress = new Uri(ConfigurationManager.AppSettings["ServiceUrl"].ToString());  
       }  
       public HttpResponseMessage GetResponse(string url)  
       {  
           return Client.GetAsync(url).Result;  
       }  
       public HttpResponseMessage PutResponse(string url,object model)  
       {  
           return Client.PutAsJsonAsync(url, model).Result;  
       }  
       public HttpResponseMessage PostResponse(string url, object model)  
       {  
           return Client.PostAsJsonAsync(url,model).Result;  
       }  
       public HttpResponseMessage DeleteResponse(string url)  
       {  
           return Client.DeleteAsync(url).Result;  
       }  
}


Create a Controller to handle a request for different action method and navigate to the corresponding view.

ProductController.cs
Product Controller in MVC application is created to handle the request received from the user action and to serve the response accordingly. Code for product controller is given below.
public class ProductController : Controller  
{  
    // GET: Product  
    public ActionResult GetAllProducts()  
    {  
        try  
        {  
            ServiceRepository serviceObj = new ServiceRepository();  
            HttpResponseMessage response = serviceObj.GetResponse("api/showroom/getallproducts");  
            response.EnsureSuccessStatusCode();  
            List<Models.Product> products = response.Content.ReadAsAsync<List<Models.Product>>().Result;  
            ViewBag.Title = "All Products";  
            return View(products);  
        }  
        catch (Exception)  
        {  
            throw;  
        }  
    }  
    //[HttpGet]  
    public ActionResult EditProduct(int id)  
    {  
        ServiceRepository serviceObj = new ServiceRepository();  
        HttpResponseMessage response = serviceObj.GetResponse("api/showroom/GetProduct?id=" + id.ToString());  
        response.EnsureSuccessStatusCode();  
        Models.Product products = response.Content.ReadAsAsync<Models.Product>().Result;  
        ViewBag.Title = "All Products";  
        return View(products);  
    }  
    //[HttpPost]  
    public ActionResult Update(Models.Product product)  
    {  
        ServiceRepository serviceObj = new ServiceRepository();  
        HttpResponseMessage response = serviceObj.PutResponse("api/showroom/UpdateProduct", product);  
        response.EnsureSuccessStatusCode();  
        return RedirectToAction("GetAllProducts");  
    }  
    public ActionResult Details(int id)  
    {  
        ServiceRepository serviceObj = new ServiceRepository();  
        HttpResponseMessage response = serviceObj.GetResponse("api/showroom/GetProduct?id=" + id.ToString());  
        response.EnsureSuccessStatusCode();  
        Models.Product products = response.Content.ReadAsAsync<Models.Product>().Result;  
        ViewBag.Title = "All Products";  
        return View(products);  
    }  
    [HttpGet]  
    public ActionResult Create()  
    {  
        return View();  
    }  
    [HttpPost]  
    public ActionResult Create(Models.Product product)  
    {  
        ServiceRepository serviceObj = new ServiceRepository();  
        HttpResponseMessage response = serviceObj.PostResponse("api/showroom/InsertProduct", product);  
        response.EnsureSuccessStatusCode();  
        return RedirectToAction("GetAllProducts");  
    }  
    public ActionResult Delete(int id)  
    {  
        ServiceRepository serviceObj = new ServiceRepository();  
        HttpResponseMessage response = serviceObj.DeleteResponse("api/showroom/DeleteProduct?id=" + id.ToString());  
        response.EnsureSuccessStatusCode();  
        return RedirectToAction("GetAllProducts");  
    }  
}


Views are created in ConsumeWebApi MVC application to consume the service.

GetAllProducts.cshtml
.cshtml represents Views (UI) and this View displays all the products available which are received from API call in the corresponding method.

@model IEnumerable<ConsumeWebApi.Models.Product>  
 
@{  
    ViewBag.Title = "GetAllProducts";  
}  
 
<h2>GetAllProducts</h2>  
 
<p>  
    @Html.ActionLink("Create New", "Create")  
</p>  
<table class="table">  
    <tr>  
        <th>  
            @Html.DisplayNameFor(model => model.ProductName)  
        </th>  
        <th>  
            @Html.DisplayNameFor(model => model.Quantity)  
        </th>  
        <th>  
            @Html.DisplayNameFor(model => model.Price)  
        </th>  
        <th></th>  
    </tr>  
 
@foreach (var item in Model) {  
    <tr>  
        <td>  
            @Html.DisplayFor(modelItem => item.ProductName)  
        </td>  
        <td>  
            @Html.DisplayFor(modelItem => item.Quantity)  
        </td>  
        <td>  
            @Html.DisplayFor(modelItem => item.Price)  
        </td>  
        <td>  
            @Html.ActionLink("Edit", "EditProduct", new { id = item.ProductId, name= item.ProductName, quantity=item.Quantity, prod = item }) |  
            @Html.ActionLink("Details", "Details", new { id=item.ProductId }) |  
            @Html.ActionLink("Delete", "Delete", new { id=item.ProductId })  
        </td>  
    </tr>  
}  
 
</table>


Create.cshtml
This View allows the user to create a product and insert into the database through WebAPI call which is done in corresponding action method.
@model ConsumeWebApi.Models.Product  
 
@{  
    ViewBag.Title = "Create";  
}  
 
<h2>Create</h2>  
 
@using (Html.BeginForm())   
{  
    @Html.AntiForgeryToken()  
      
    <div class="form-horizontal">  
        <h4>Product</h4>  
        <hr />  
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })  
        <div class="form-group">  
            @Html.LabelFor(model => model.ProductName, htmlAttributes: new { @class = "control-label col-md-2" })  
            <div class="col-md-10">  
                @Html.EditorFor(model => model.ProductName, new { htmlAttributes = new { @class = "form-control" } })  
                @Html.ValidationMessageFor(model => model.ProductName, "", new { @class = "text-danger" })  
            </div>  
        </div>  
 
        <div class="form-group">  
            @Html.LabelFor(model => model.Quantity, htmlAttributes: new { @class = "control-label col-md-2" })  
            <div class="col-md-10">  
                @Html.EditorFor(model => model.Quantity, new { htmlAttributes = new { @class = "form-control" } })  
                @Html.ValidationMessageFor(model => model.Quantity, "", new { @class = "text-danger" })  
            </div>  
        </div>  
 
        <div class="form-group">  
            @Html.LabelFor(model => model.Price, htmlAttributes: new { @class = "control-label col-md-2" })  
            <div class="col-md-10">  
                @Html.EditorFor(model => model.Price, new { htmlAttributes = new { @class = "form-control" } })  
                @Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" })  
            </div>  
        </div>  
 
        <div class="form-group">  
            <div class="col-md-offset-2 col-md-10">  
                <input type="submit" value="Create" class="btn btn-default" />  
            </div>  
        </div>  
    </div>  
}  
 
<div>  
    @Html.ActionLink("Back to List", "GetAllProducts")  
</div>  

Details.cshtml
This View allows the user to see the particular product through WebAPI call which is done in the corresponding action method.
@model ConsumeWebApi.Models.Product  
 
@{  
    ViewBag.Title = "Detail";  
}  
 
<h2>Detail</h2>  
 
<div>  
    <h4>Product</h4>  
    <hr />  
    <dl class="dl-horizontal">  
        <dt>  
            @Html.DisplayNameFor(model => model.ProductName)  
        </dt>  
 
        <dd>  
            @Html.DisplayFor(model => model.ProductName)  
        </dd>  
 
        <dt>  
            @Html.DisplayNameFor(model => model.Quantity)  
        </dt>  
 
        <dd>  
            @Html.DisplayFor(model => model.Quantity)  
        </dd>  
 
        <dt>  
            @Html.DisplayNameFor(model => model.Price)  
        </dt>  
 
        <dd>  
            @Html.DisplayFor(model => model.Price)  
        </dd>  
 
    </dl>  
</div>  
<p>  
    @Html.ActionLink("Edit", "EditProduct", new { id = Model.ProductId }) |  
    @Html.ActionLink("Back to List", "GetAllProducts")  
</p>  


EditProduct.cshtml
This View allows the user to edit product and update database through WebAPI call which is done in the corresponding action method.
@model ConsumeWebApi.Models.Product  
 
@{  
    ViewBag.Title = "EditProduct";  
}  
 
<h2>EditProduct</h2>  
 
 
@using (Html.BeginForm("Update", "Product", FormMethod.Post))  
{  
    @Html.AntiForgeryToken()  
 
    <div class="form-horizontal">  
        <h4>Product</h4>  
        <hr />  
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })  
        @Html.HiddenFor(model => model.ProductId)  
 
        <div class="form-group">  
            @Html.LabelFor(model => model.ProductName, htmlAttributes: new { @class = "control-label col-md-2" })  
            <div class="col-md-10">  
                @Html.EditorFor(model => model.ProductName, new { htmlAttributes = new { @class = "form-control" } })  
                @Html.ValidationMessageFor(model => model.ProductName, "", new { @class = "text-danger" })  
            </div>  
        </div>  
 
        <div class="form-group">  
            @Html.LabelFor(model => model.Quantity, htmlAttributes: new { @class = "control-label col-md-2" })  
            <div class="col-md-10">  
                @Html.EditorFor(model => model.Quantity, new { htmlAttributes = new { @class = "form-control" } })  
                @Html.ValidationMessageFor(model => model.Quantity, "", new { @class = "text-danger" })  
            </div>  
        </div>  
 
        <div class="form-group">  
            @Html.LabelFor(model => model.Price, htmlAttributes: new { @class = "control-label col-md-2" })  
            <div class="col-md-10">  
                @Html.EditorFor(model => model.Price, new { htmlAttributes = new { @class = "form-control" } })  
                @Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" })  
            </div>  
        </div>  
 
 
        <div class="form-group"><div class="col-md-offset-2 col-md-10">  
                <input type="submit" value="Save" class="btn btn-default" />  
            </div>  
        </div>  
    </div>  
 
}  
 
<div>  
    @Html.ActionLink("Back to List", "GetAllProducts")  
</div>  


Step 5 – Set Project Startup Order

This step is necessary and has to be set up because this solution needs WebApiService application to keep running and serve the request. ConsumeWebAPI application will create a request to WebApiService and receive a response back.
So, in order to make two projects to keep up and running, this step is performed.
Whereas if WebApiService is hosted in IIS, then only one project which consumes the service can be started, i.e., MVC or postman.


Output Screens

    Get All Products View.

Create Product View.


Edit Product View.


Detailed View of a product.


Product table data in Product table of SQL Database.

Web API can be self-hosted (service and consuming application in the same solution) as discussed in this example or it can be deployed on IIS server. JSON is the widely used request type in services as it is supported by a wide range of client devices. Enjoy creating your own service.



ASP.NET MVC Hosting - HostForLIFEASP.NET :: Layouts And _Viewstart.cshtml In MVC

clock August 2, 2022 09:52 by author Peter

In this blog, we will discuss about Layouts and what is the significance of _viewstart.cshtml in Razor views. The intention of this blog is to understand the way how _viewstart.cshtml works in MVC. The reason to write this blog is I faced an issue with _viewstart.cshtml,  when I was using HandleError attribute.


What is Layout?
We all know that layouts are like the master pages in Webforms. Simply, the common UI code, which can be used in many views can go into a common view called layout. Usually, we place all the layout pages in the shared folder.

How to use Layouts in MVC?
The following are the different ways to use the layouts:

Using Layout in the View.
    @{  
    ViewBag.Title = "Index";  
    Layout = "~/Views/Shared/_Layout.cshtml";  
    }  

If we declare the code above, given above in the Index.cshtml, this will be rendered along with the HTML content of the _Layout.cshtml. This is the way, we regularly follow.

Assigning Layout in Controller's Action method.

If we work with real the time Applications, we will come across the situations, like to use the different layouts , based on the action called.

For example, I am looking for the list of the students. At this point, Layout would be different for admin and a Teacher but, both of them use same Razor View. Here, we will assign the Layout at an Action level.

We can see assigning the Layout at Action Method in the following code snippet.
If logged in as an admin:
    public List < Student > GetStudentList() {  
        return View("StudentList", "~/Views/Shared/AdminLayout.cshtml");  
    }  
    If Logged in as Teacher: public List < Student > GetStudentList() {  
        return View("StudentList", "~/Views/Shared/TeacherLayout.cshtml");  
    } 

Declaring Layout at _Viewstart.cshtml.

_Viewstate.cshtml plays an important and a tricky role in Razor views. It was introduced in MVC 3 along with Razor views. _Viewstart.cshtml is used to place common UI logic across the Views in the folder, where it is located. This means, the views in a single folder which is having _Viewstart.cshtml will be rendered along with it.

For example: If we observe the views folder of an MVC project, we will see _Viewstart.cshtml in the folder.

Thus, the views in Home and OpenAccess will be rendered along with the UI in _Viewstart.cshtml. We need not to declare anything in the views. This will be done automatically by the framework.

Benefit
By doing so, we can change the layout at a single place only. Otherwise, we have to change the number of views.

Notes
    The inner layouts like a layout in Home/Index will be overriden by _Viewstart.cshtml.
    We can have n-number of _Viewstart.cshtml files in a project. But each should be placed in a folder. Alll the views in the folder will be effected with this.
    _Viewstart.cshtml will be called after the inner view.(Ex: Home/Index)

Finally My problem was
I used HandlerError attribute in a controller. If any exception is caught in the Action method, it should go to error.cshtml, but It was not called as error.cshtml view, placed in a folder, which has _Viewstart.cshtml. Thus, _Viewstart.cshtml will be called after the error.cshtml. _Viewstart.cshtml has the layout,  where I had a Null Reference exception. At last, I removed Layout from _Viewstart and able to see error.cshtml page.

Conclustion
In this blog, we have discussed about the different ways to place layouts in MVC and use of _Viewstart.cshtml. Finally, use _Viewstart.cshtml effectively.



ASP.NET MVC Hosting - HostForLIFEASP.NET :: Adding Dynamic Chart In ASP.NET MVC 6

clock August 1, 2022 10:10 by author Peter

Dynamic Chart displays live data to ASP.NET MVC projects through API and databases. Many javascript libraries have been used to implement charts, like Chart.js, CanvasJS, etc. However, I will be using CanvasJS in this article.

In this article, I will describe the following points:
    What is CanvasJS?
    Creating an ASP.NET MVC 6 Project
    Using CanvasJS in ASP.NET MVC 6 Project
    Inserting Live API Data in Chart
    Formatting Chart

Prerequisites:
    Visual Studio 2022 installed on your machine
    Basic knowledge of JavaScript

What is CanvasJS?
CanvasJS is a JavaScript library with rich UI and multiple functionalities. It allows us to implement charts in our ASP.NET MVC project. We can provide both static and dynamic data to render in charts. CanvasJS generates multiple types of charts, like Line Chart, Bar Chart, Area Chart, Donut Chart, and a lot more. To know more about CanvasJS, please refer here.

Creating an ASP.NET MVC Project
To create an ASP.NET MVC Project, please refer to my previous article, linked below:
    Creating an ASP.NET MVC 6 Project

Using CanvasJS in ASP.NET MVC Project
To implement the chart, you need to follow the steps given below.

First, you will add the CanvasJS JavaScript file link in the _Layout.cshtml file as given below:
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>

Now, add the chart inside Home View using JavaScript as given below:
<script type="text/javascript">

window.onload = function () {
  var chart = new CanvasJS.Chart("chartContainer", {
    title:{
      text: "My First Chart in ASP.NET MVC"
    },
    data: [
    {
      // Change type to "doughnut", "line", "splineArea", etc.
      type: "column",
      dataPoints: [
        { label: "apple",  y: 10  },
        { label: "orange", y: 15  },
        { label: "banana", y: 25  },
        { label: "mango",  y: 30  },
        { label: "grape",  y: 28  }
      ]
    }
    ]
  });
  chart.render();
}
</script>

You need to create a <div> tag inside the <body> tag, having id chartContainer to render the the function given above.
<div id="chartContainer" style="height: 400px; width: 60%;"></div>

Markup
    Set the height and width according to your needs, as given in the above code.

Output


Inserting Live API Data in Chart
Above, we used static data to represent the chart. Now we will use live API data. We have created a demo sale API that contains data on monthly sales.


Formatting Chart
We can show our data in any form, like a line chart, area chart, etc. if we change the type to the line as given below:

data: [
    {
      // Change type to "doughnut", "line", "splineArea", etc.
      type: "line",
      dataPoints:
      @Html.Raw(ViewBag.Data)
      //[
      //  { label: "apple",  y: 10  },
      //  { label: "orange", y: 15  },
      //  { label: "banana", y: 25  },
      //  { label: "mango",  y: 30  },
      //  { label: "grape",  y: 28  }
      //]
    }
    ]


Output

This Article In a Nutshell:
    First, you need to create an ASP.NET MVC  project in Visual Studio 2022.
    Add the CanvasJs JavaScript file link in your View from here.
    Now, add the JavaScript code to your View.
    Map the API data with the Chart data points and store it in the ViewBag.
    Use ViewBag data inside JavaScript code.

Conclusion
In this way, you can add charts to your ASP.NET MVC project. The most important part is mapping the API data to the chart data points so that you can easily store that into ViewBag. Then, you can use it inside JavaScript code.



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

clock July 20, 2022 07:50 by author Peter

In this article, we will learn how to generate Barcode in ASP.NET MVC Core 6 by simply entering text, numbers, and a combination of both in the textbox and click on generate Barcode button. I found a very useful library for generating Barcode which is IronBarcode. You can install IronBarcode through the NuGet package. It supports .Net Core, Standard & Framework, and 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 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 Configure your new project dialog, enter GenerateBarcodeMVCCore6_Demo for Project name. It's important to name the project GenerateBarcodeMVCCore6_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.


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 in order 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.

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 for use.

Add a class in the Models folder and write or copy-paste the below code.
using System.ComponentModel.DataAnnotations;

namespace GenerateBarcodeMVCCore6_Demo.Models
{
    public class GenerateBarcodeModel
    {
        [Display(Name = "Enter Barcode Text")]
        public string BarcodeText
        {
            get;
            set;
        }
    }
}


We will use exiting HomeController to write the code.
using GenerateBarcodeMVCCore6_Demo.Models;
using IronBarCode;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using System.Drawing;

namespace GenerateBarcodeMVCCore6_Demo.Controllers
{
    public class HomeController : Controller
    {
        private readonly IWebHostEnvironment _environment;
        public HomeController(IWebHostEnvironment environment)
        {
            _environment = environment;
        }

        public IActionResult CreateBarcode()
        {
            return View();
        }

        [HttpPost]
        public IActionResult CreateBarcode(GenerateBarcodeModel generateBarcode)
        {
            try
            {
                GeneratedBarcode barcode = IronBarCode.BarcodeWriter.CreateBarcode(generateBarcode.BarcodeText, BarcodeWriterEncoding.Code128);
                barcode.ResizeTo(400, 120);
                barcode.AddBarcodeValueTextBelowBarcode();
                // Styling a Barcode and adding annotation text
                barcode.ChangeBarCodeColor(Color.BlueViolet);
                barcode.SetMargins(10);
                string path = Path.Combine(_environment.WebRootPath, "GeneratedBarcode");
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }
                string filePath = Path.Combine(_environment.WebRootPath, "GeneratedBarcode/barcode.png");
                barcode.SaveAsPng(filePath);
                string fileName = Path.GetFileName(filePath);
                string imageUrl = $"{this.Request.Scheme}://{this.Request.Host}{this.Request.PathBase}" + "/GeneratedBarcode/" + fileName;
                ViewBag.QrCodeUri = imageUrl;
            }
            catch (Exception)
            {
                throw;
            }
            return View();
        }

    }
}


Next, "Add View" - right-click on the CreateBarcode action method in HomeController class. Select "Add View" then select "Razor View." Next, click on the "Add" button.
    In the view name CreateBarcode default name as action method in HomeController.
    Template "Create"
    In the Model, class drop-down, select GenerateBarcodeModel(GenerateBarcodeMVCCore6_Demo.Models).
    Select Add.

The following is the CreateBarcode View code.
@model GenerateBarcodeMVCCore6_Demo.Models.GenerateBarcodeModel

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

<h4>Generate Barcode</h4>

<div class="row">
    <div class="col-md-4">
        <form asp-action="CreateBarcode">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="BarcodeText" class="control-label"></label>
                <input asp-for="BarcodeText" class="form-control" />
                <span asp-validation-for="BarcodeText" class="text-danger"></span>
            </div>
            <br />
            <div class="form-group">
                <input type="submit" value="Generate Barcode" 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 Barcode using the IronBarcode library. We can save Barcode as jpg, png images, pdf, or HTML files. We can also add a logo to our Barcode 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 :: Best Practices To Secure ASP.NET Core MVC Web Applications

clock July 18, 2022 09:29 by author Peter

ASP.NET Core MVC is a web development framework, widely used by developers around the world, to develop web applications. These web applications have proven to be vulnerable to attacks from different sources, though, and it is our responsibility to safeguard our data. This article will help you develop a secure ASP.NET Core MVC web application. The following are the best practices recommended for avoiding vulnerabilities in your applications:


    Cross-Site Scripting (XSS)
    SQL Injection
    Cross-Site Request Forgery (CSRF)
    Custom Error Page for Error Handling
    Version Discloser
    Enforce SSL (Secure Sockets Layer) and HSTS
    XXE (XML External Entity) Attack
    Improper Authentication and Session Management
    Sensitive Data Exposure and Audit Trail
    File Upload Validation

Cross-Site Scripting (XSS)
What is Cross-Site Scripting?

Injecting a malicious script through the input/form field of a webpage with the intention to steal confidential information such as login credentials or other authentication information, cookies, and session values is called a cross-site scripting (XSS) attack.

Script injection can be carried out in the following ways:
    Form Inputs
    URL Query Strings
    HTTP Headers

How to Prevent Cross-Site Scripting
Cross-site scripting attacks can be prevented in the following ways:
    Regular Expression Attributes
    Regular Expression Object Model
    HTML Encoding
    URL Encoding

Regular Expression Attribute
You can use regular expressions to validate the user’s form inputs. So, you can deny malicious characters, or symbols, or allow only acceptable required characters in the input field before allowing the user to proceed further. To learn more about regular expression attributes, refer to the RegularExpressionAttribute Class docs.

Regular Expression Object Model

Just like the regular expression attribute, using the regular expression object model, you can validate user inputs by calling static methods of the Regex class.
To learn more about the regular expression object model, refer to The Regular Expression Object Model.
Note: You can do both client-side and server-side input validations.

HTML Encoding

The MVC Razor engine automatically encodes all inputs so that the script part provided in any field will never be executed.
Note: If you want to use raw text without encoding, you need to use the syntax @Html.Raw().

URL Encoding
Usually, we use plain text in URL query strings, which can be used to launch XSS attacks. So, we should encode the query parameter input in the URL.
We have a built-in library in NuGet for encoding and decoding the text:
string encodedValue = System.Net.WebUtility.UrlEncode("raw-string-text");
string decodedValue = System.Net.WebUtility.UrlDecode(encodedValue);


SQL Injection
What is SQL Injection?

It is a dangerous attack wherein unauthorized users inject malicious SQL code that then runs in your database, allowing the attackers to access confidential information stored in it. Refer to the Wikipedia article on SQL injection to learn more about SQL injection.

How to Prevent SQL Injection

The SQL injection attack can be prevented in the following ways:
    Validate inputs
    Use stored procedures
    Use parameterized queries
    Use Entity Framework or any other ORM
    Use least-privileged DB access
    Store encrypted data

Validate Inputs
Defending against SQL injection by validating inputs requires the following actions:
    Validate the user inputs on both the client-side and server-side.
    Do not allow special characters that are involved in SQL scripts.
    Use regular expressions and data annotations to validate inputs.

Use Stored Procedures
Using stored procedures will prevent SQL injection, but we should still validate the input parameters passed to the stored procedures.

Use Parameterized Queries
If you want to use inline queries, you must use parameterized queries to prevent SQL injection. The following code example demonstrates a parameterized query.

Use Entity Framework or any other ORM
ORM stands for the object-relational mapper, which maps SQL objects to your application class object.

If you are using the Entity framework properly, you are not prone to SQL injection attacks because Entity Framework internally uses parameterized queries.

Use Least-Privileged DB Access

We should limit the DB user permissions for tables that have confidential data. For example, we should restrict the insert, update, and delete permissions for tables related to payments and transactions, and we should also limit permissions for tables that store a user’s personal information. If a user only works with Select queries, then we must give permission only to the Select statement, and should not provide permissions for Insert, Update, and Delete statements.

Store Encrypted Data
We should not store confidential information like email addresses and passwords as plain text in a database. It should be stored in an encrypted format.
Cross-Site Request Forgery (CSRF)

What is Cross-Site Request Forgery?
An attacker acts as a trusted source and sends some forged data to a site. The site processes the forged data because it believes it is coming from a trusted source.
To learn how this attack works, refer to the Cross-Site Request Forgery (CSRF) article on the OWASP wiki.
Let’s discuss an example of this type of attack: when a user transfers funds from one bank account to another, a trusted connection is established between the user and the bank site after the user logs in successfully.
At the same time, the user clicks a malicious link in an email sent by an attacker.
As the secure session is already established between the user and the bank site, the attacker uses this connection and performs some malicious activity such as fund transfers.
However, this attack is only a risk on the server-side (web application), not the end-user side.

How to Prevent Cross-Site Request Forgery?
We can prevent this attack by using AntiForgeryToken.

We can use the HTML tag helper asp-antiforgery in an HTML attribute and set its value as true. By default, this value will be false. If we set this value as true, it will generate an anti-forgery token. Then, we need to add the [ValidateAntiForgeryToken] attribute to the form post-action method to check whether a valid token is generated.

Custom Error Page for Error Handling
Sometimes you may not properly write error-handling code in your web application. This can lead us to expose sensitive information such as database configuration info, table names, stored procedures, data structures, and programming coding structures to users.

How to Add Proper Custom Error Handling?
There are two ways to add custom error-handling pages in an ASP.NET Core application.
The first approach is to create a custom error-handling attribute using ExceptionFilterAttribute. This attribute will handle the exception.
We can override the OnException method and write exceptions in text files organized by date, and then store the files in the desired folder path. We can also store the exception in a database. Finally, we’ll redirect the route to a custom error page as in the following code.
public class CustomExceptionFilterAttribute: ExceptionFilterAttribute
{
    //write the code logic to store the error here
    var result = new RedirectToRouteResult(
    new RouteValueDictionary
    {
        {"controller", "Error"}, {"action", "CustomError"}
    });
}

Then, we need to register this filter globally inside the ConfigureServices method in the Startup.cs file.

The second approach is to configure UseExceptionHandler in the production environment.

Here, we have written code to show the custom error page in the error controller only if the hosting environment is production, so the staging and development environments will not show the custom error page, but instead show the actual error in the browser.

Version Discloser

We should hide the version information of what we used to develop the application from end-users because if an attacker learns the specific version, then they may try to target an attack on that specific version based on a previously disclosed vulnerability.

Whenever the browser sends an HTTP request to the server in response, the browser gets a response header, which contains the following information:
    server
    x-powered-by
    x-aspnet-version
    x-aspnetmvc-version
    x-sourcefiles

The server shows information about the web server that is used. For example, a response could contain the following:
    Server: Microsoft-IIS/10.0: Application is hosted by Microsoft-IIS version 10.0.
    X-Powered-By: ASP.NET: This shows the ASP.NET framework your website is running on.
    X-Aspnet-Version: 4.0.30319: This shows the ASP.NET framework version your website is running on.
    X- AspnetMvc-Version: 4.0: This shows the ASP.NET MVC framework version your website is running on.
    X-SourceFiles: This will only be generated for localhost requests and serves debugging purposes.

How to Hide Header Values?
Server Header

We can remove the Server header by adding the line “UseKestrel(c => c.AddServerHeader = false)” in the CreateWebHostBuilder method in the Program.cs class.


X-Powered-By Header
To remove the X-Powered-By header, we need to add a web configuration file, and in that web config file, we need to add an element that removes the X-Powered-By element under <system.webServer>.
<system.webServer>
  <httpProtocol>
    <customHeaders>
      <remove name="X-Powered-By" />
    </customHeaders>
  </httpProtocol>
</system.webServer>


We can remove this from the IIS settings too. Select the header and remove it.

X-Aspnet-Version Header
To remove the X-Aspnet-Version header, make the following change in the web configuration file:
<system.web>
  <httpRuntime enableVersionHeader="false" />
</system.web>

X- AspnetMvc-Version Header
To remove the X-AspnetMvc-Version header, add the following line where the application starts in Global.aspx:
protected void Application_Start(object sender, EventArgs e)
{
  MvcHandler.DisableMvcResponseHeader = true;
}


Enforce SSL (Secure Sockets Layer) and HSTS
What is SSL?

SSL stands for Secure Sockets Layer, and it establishes a secure or encrypted connection between client and server. With SSL, the requests passed between the client browser and the server, and the responses from the server to the client browser will be encrypted to maintain the integrity of the data.
We can use HTTPS (HyperText Transfer Protocol Secure) to secure your ASP.NET Core application.
In ASP.NET Core 2.1 and later versions, we can easily create an application that is configured over HTTPS. We can also configure HTTPS with ASP.NET Core before .NET Core Framework version 1.1, but it is somewhat difficult to do.
An option to configure the web application over HTTPS is available when selecting the web application template in Visual Studio as shown in the following screenshot.

What is HSTS (HTTP Strict Transport Security)?
HSTS is a web security policy that protects your web application from downgrade protocol attacks and cookie hijacking. It forces the web server to communicate over an HTTPS connection. It always rejects insecure HTTP connections.

The ASP.NET Core template, by default, adds HSTS middleware. It is not recommended for use in the development environment as the browser caches the HSTS header.

We can override a few options when configuring HSTS. They are:

    MaxAge: Timespan that defines the max-age of the Strict-Transport-Security The default value is 30 days.
    IncludeSubDomains: If this value is set to true, the Strict-Transport-Security header will be available for subdomains too.
    Preload: Adds preload support to the Strict-Transport-Security
    ExcludedHosts: A list of host names that will not add the HSTS header.

The ASP.NET Core default template also adds another middleware that redirects requests from non-secure HTTP. It uses the default redirect status code (307) to redirect the request. We can also override the default option.

XXE (XML External Entity) Attack
If your application uses logic to parse an XML file that is uploaded by an end-user, you are at risk of an XXE (XML External Entity) attack. In this kind of attack, a weakly configured XML parser processes an XML input that contains malicious XML code or a reference to an external entity. This kind of attack can cause a denial-of-service attack by injecting entities within entities, which makes your server utilization too high, resulting in a server shutdown. This kind of attack is also known as a “billion laughs attack”.

How to Prevent This Attack
If we use XmlTextReader to parse XML files, we must set the DtdProcessing property to Prohibit or Ignore.

If it is set to Prohibit, an exception will be thrown if a DTD (Document Type Definition) is identified.

If it is set to Ignore, any DTD specification in the document will be ignored and the processing of the document will continue.

If we set it to Parse, it will parse any DTD specifications in the document. DtdProcessing is set to Parse by default. It is potentially vulnerable.

Improper Authentication and Session Management
Most web applications have an authentication module, and we should be careful when writing code for it. We could make mistakes like not removing the authentication cookies after a successful logout. This kind of mistake allows attackers to steal user credentials such as cookies and session values and may result in attackers being able to access the complete application and cause major negative impacts.

The following mistakes can help attackers steal data:
    Insecure connection (without SSL).
    Predictable login credentials.
    Storing plain (unencrypted) credentials.
    Improper application logouts.

How to Avoid These Mistakes
    Remove cookies after successful logout.
    Secure cookies and sessions by using SSL.
    Secure cookies by setting HTTP only.

Refer to the following code to remove session values and authentication cookies (.AspNetCore.Session) after a user logs out.

To set HttpOnly on cookies in ASP.NET Core, refer to the following code:
CookieOptions option = new CookieOptions {Expires = DateTime.Now.AddHours(24), HttpOnly = true};
HttpOnly is a flag that is used to set any cookie, and it cannot be accessed from client-side scripts.
To globally set up HttpOnly, configure the UseCookiePolicy method in Startup.cs as shown in the following screenshot.

Sensitive Data Exposure and Audit Trail
We always manage a user’s personal, important data in web applications. There are many places in an app where we may expose and store sensitive data as if it is ordinary information, or adequately secure some but not all sensitive information without realizing it. If attackers can access sensitive data we overlooked, they will misuse it.

What Do We Need to Do to Avoid These Mistakes?

  1. Send sensitive data in an encrypted format using a suitable encryption algorithm. For example, passing a customer mail address over a URL with encryption.

  2. Use SSL and access web applications in production in HTTPS mode.

  3. Do not store sensitive data that includes database or application code anywhere. If you store it, use a strong encryption algorithm to encrypt the data, and then store it.

Audit Trail

It is a best practice to keep monitoring your production web application’s activity logs at regular intervals. We can set up logs to be collected using IIS logs, or we can store our logs in text files or databases. Based on the logs, we can gather insights on any errors or performance issues in the production application, and also, if anyone tries to attack the application, we can identify their attempts.

File Upload Validation

If your web app has file upload control, attackers will have the chance to upload malicious script files that cause problems. So, proper file validation is always required.

The main validation we do on files is validating the file extension. However, attackers can change their file’s extension and upload it anyway. For example, if you allow only image files, an attacker can save their script file with a .jpeg extension and upload it. In this case, the file extension validation accepts the file because it considers it an image file, even though it is really a malicious script file.

How to Do Proper Validation?

  1. First, check the file upload count. If the upload count is zero, no file is uploaded. If the upload count is greater than zero, proceed with further validation.

  2. Check the file extension. This will allow only valid extension files. Sometimes, attackers can still pass malicious files with allowed extensions. In this case, do further validation.

  3. Check the file content type and file bytes.

  4. Only allow uploading the file when the previous three steps are successfully validated.



ASP.NET MVC Hosting - HostForLIFEASP.NET :: Inserting Rich Text Editor In ASP.NET MVC 6

clock July 15, 2022 08:04 by author Peter

We can insert a rich text editor in our project using JQuery and ASP.NET MVC 6. We have many open-source libraries like TinyMCE, CKEditor, and Summernote, allowing us to insert text editors in the ASP.NET MVC project. However, I will be using TinyMCE in this article.


In this article, I will describe the following points.
    What is TinyMCE
    Creating an ASP.NET MVC 6 Project
    Installing TinyMCE
    Using TinyMCE in ASP.NET MVC 6 Project
    Formating TinyMCE Text Editor

Prerequisites
    Visual Studio 2022 is installed on your machine
    Basic knowledge of JQuery

What is TinyMCE
TinyMCE is an open-source rich text editor. The output created in this editor is in HTML5 and it can include lists, tables, and other valuable elements. To know more about the TinyMCE please refer here. The below-given image shows a basic UI of the TinyMCE text editor.

Creating An ASP.NET MVC 6 Project
To create an ASP.NET MVC project you need to do the following steps.
    Open Visual Studio 2022 and create a new project as given in the below image,

Now select ASP.NET Core Web App(Model View Controller) from the project template and click Next as given in the below image.


Now give the proper name to your project and solution as given below.


In this step, you have to select your .NET version which is 6.0(Long-term-support) as given in the below image.


You have successfully created an ASP.NET MVC project. Now you have to install the TinyMCE text editor.

Installing TinyMCE

We can easily install TinyMCE from the official website. To install TinyMCE in our project follow the steps given below.
Visit the TinyMCN official website here and download the TinyMCE SDK as given below.




Unzip the downloaded file and copy the inner tinymce folder in your project inside the wwwroot->js->tinymce as given below.


You have successfully installed TinyMCE SDK and imported it into your project.
Using TinyMCE In ASP.NET MVC Project

Now you have to use this TinyMCE Text Editor in your project using JQuery. To use the text editor first you need to add a Model class and add an HTML form in the Index View of the Home controller. To use TinyMCE Editor follow the below-given steps.

    First, you will add a Model class inside the Models folder as given below.

Add the below-given Properties in the TextEditor.cs file.
namespace TextEditorProject.Models
{
    public class TextEditor
    {
        public string Title { get; set; }  // for the title of the text
        public string Body { get; set; }  // for the body of the text
    }
}

In the above code, you have added two properties Title and Body for the title of the content and the body will contain the content itself.
Now add a form in the Index.cshtml file with proper HTML Helper Tags in the Home View.
<form method="POST">

  <div asp-validation-summary="ModelOnly" class="text-danger"> </div>

  <!-- title input -->

  <div class="form-outline mb-4">
  <label class="form-label" asp-for="Title"></label>
  <div>
  <input asp-for="Title" class="form-control" />
  <span asp-validation-for="Title" class="text-danger"></span>
  </div>
  </div>

  <!-- body input -->

  <div class="form-outline mb-4">
      <label class="form-label" asp-for="Body"></label>
      <div>
        <textarea asp-for="Body" class="form-control"></textarea>
        <span asp-validation-for="Body" class="text-danger"></span>
      </div>
  </div>
 <input type="Submit" class="btn btn-primary" value="Create" />
</form>

In the above code, you have added one input for the Title and a Textarea for the body.
Now in the _Layout.cshtml file you need to add the tinymce javascript file link as given below.
<script src="~/js/tinymce/tinymce.min.js" referrerpolicy="origin"></script>

The final step is to add jquery code at the end of the Index.cshtml file as given below
@section Scripts{
     <script>
           tinymce.init({
               selector: 'textarea#body'
           });
       </script>
}


In the above code, you have the init method that will initialize the tinymce at the selector textarea.  
Output

Formatting TinyMCE Text Editor
The Text Editor you have created is very basic. To make it more interactive you can add a lot of plugins, toolbar, menu, and much more to this which are also provided by the TinyMCE. Now we will add more plugins to this as given below.
<script>
    tinymce.init({
    selector: 'textarea#Body',
    width: 600,
    height: 300,
    plugins: [
      'advlist', 'autolink', 'link', 'image', 'lists', 'charmap', 'preview',
       'anchor', 'pagebreak',
      'searchreplace', 'wordcount', 'visualblocks', 'visualchars', 'code',
      'fullscreen', 'insertdatetime',
      'media', 'table', 'emoticons', 'template', 'help'
    ],
 toolbar: 'undo redo | styles | bold italic | alignleft aligncenter alignright alignjustify | ' +
'bullist numlist outdent indent | link image | print preview media fullscreen | ' +
      'forecolor backcolor emoticons | help',
    menu: {
      favs: { title: 'My Favorites', items: 'code visualaid |
       ' + 'searchreplace | emoticons' }
    },
    menubar: 'favs file edit view insert format tools table help',
    content_css: 'css/content.css'
           });
</script>


In the above code, you have added a lot of plugins, toolbar, menu, and menubar.

Output


As we can see in the above image you have added a lot more functionality to this Text Editor.



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 :: Swagger For .NET MVC Web API

clock July 8, 2022 09:38 by author Peter

Swagger (OpenAPI) is a language-agnostic specification for describing REST APIs. It allows both computers and humans to understand the capabilities of a REST API without direct access to the source code. Swagger UI offers a web-based UI that provides information about the service, using the generated OpenAPI specification. Swagger UI is an alternative to Postman.


I used Swagger more than several times in my articles, but just as a minor tool associated with different other major topics. When I tried to get info on Swagger, I had to search from these articles, which were not convenient. So, I rewrote these two articles, especially about Swagger for .NET MVC Web API or .NET Core MVC Web API.

This article is part of another article: Exception Handling (2), In ASP.NET MVC Web API, we got Swagger related part here. You can see details from there.
Step 1 - Create an ASP.NET MVC Web API app

We use the version of Visual Studio 2019 16.8 and .NET Framework 4.7.2 to build the app.

    Start Visual Studio and select Create a new project.
    In the Create a new project dialog, select ASP.NET Web Application (.NET Framework) > Next.
    In the Configure your new project dialog, enter ErrorHandlingWebAPI for Project name > Create.
    In the Create a new ASP.NET Web Application dialog, select Web API > Creat

Build and run the app, you will see the following image shows the app,

Step 2 - Add one empty ApiController
Add one empty apiController into the app, with the name as ErrorHandlingWebAPIController:
    Right click Controllers > add > controller.
    In the Add New Scaffolded Item dialog, select Web API in the left pane, and
    Web API 2 Controller - Empty > Add.
    In the Add Controller dialog, Change ErrorHandlingWebAPIController for controller name > Add.

Step 3 - Add code into the controller
We add the following code into the controller,
[Route("CheckId/{id}")]
[HttpGet]
public IHttpActionResult CheckId(int id)
{
    if (id < 10) // No error hanbdling at all:
    {
        int a = 1;
        int b = 0;
        int c = 0;
        c = a / b; //it would cause exception.
    }
    else if (id <20) // Error handling by HttpResponseException with HttpStatusCode
    {
        throw new HttpResponseException(HttpStatusCode.BadRequest);
    }
    else if (id < 30) // Error handling by HttpResponseException with HttpResponseMessage
    {
        var response = new HttpResponseMessage(HttpStatusCode.BadRequest)
        {
            Content = new StringContent(string.Format("No Employee found with ID = {0}", 10)),
            ReasonPhrase = "Employee Not Found"
        };

        throw new HttpResponseException(response);
    }

    return Ok(id);
}


Step 4 - Add Swagger Client
Installing Swagger from NuGet Package Manager, from Visual Studio project,

    Right click Tools > NuGet Package Manager > Manage NuGet for Solution
    In the opened NuGet-Solution dialog: Click Browse, then Search Swagger
    Install Swashbuckle v5.6.0

Before installation of Swagger, MVC usually has four config files in folder App_Start,


 

After installation, one more file, SwaggerConfig.cs, added,

with code,
public class SwaggerConfig
{
    public static void Register()
    {
        var thisAssembly = typeof(SwaggerConfig).Assembly;
        GlobalConfiguration.Configuration
          .EnableSwagger(c => c.SingleApiVersion("v1", "ErrorHandlingWebAPI"))
          .EnableSwaggerUi();
    }
}


Step 5 - Change the default start page to the swagger

Right click Project > Properties to open the properties page, then choose Web, in Start URL, add /swagger,


Step 6 - Run the app




ASP.NET MVC Hosting - HostForLIFEASP.NET :: Consume Web API By MVC In .NET Core, Server And Framework

clock June 28, 2022 08:54 by author Peter
Microservice is a modern software development architecture: loosely-coupled architecture with application scope.  It basically includes two parts: Client and API. Theoretically, API is a server, it could be built by any language or any platform or any device. The client is the consumer of the API Server that, in turn, could be applications of a smartphone, tablet, Windows, Mac, or any kind of browser, and could be built by any platfom and language.

 
ASP.NET Web API is, specifically, a Microsoft product to produce the RESTful output through HTTP for Clients. The consumer of ASP.NET Web API could be:
  • Javascript client,
  • Angular client,
  • Node.js client,
  • jQuery client,
  • C# code such as Console, MVC, WebForm, Windows, and so on.
In this article, we will consider the C# client, and specifically an ASP.NET MVC client in .NET Core. If we Google it, we can find out a lot articles that describe the C# client to consume Web API (see some of the references at the end of this article). However, most of them seem quite complex, and even you could follow the steps to build a project, it is hard to follow the points to re-do one for yourself.

The contribution of this article is that I will try to make one-line code to build the MVC Client. Before the one-line code, we will use all of the knowledge and techniques we are familiar with to build the server and client framework.

This article will be divided in two parts, Part I (this article) will create a ASP.NET Core Web API (server), and also a ASP.NET Core MVC module (Client base). The later one will be used as a framework of the one-line code MVC Client. Part II will implement the one-line code Web API Client to be a Web API consumer.

A: Build ASP.NET MVC in .NET Core with Entity Framework Database First

This part will create a ASP.NET Core MVC application with Entity Framework Database first approach.

  • Step 1: Create an ASP.NET Core MVC application
  • Step 2: Reverse engineer Entity model from database (database first aproach for entity)
  • Step 3: Scaffold Controller with View using Entity Framework
  • Step 4: Run and Test app
At the end, you have an MVC app that can consume a database directly through entity framework.

Step 1: Create an ASP.NET Core MVC application

We use the current version of Visual Studio 2019 16.8 and .NET 5.0 SDK to build the app.

  1. Start Visual Studio and select Create a new project.
  2. In the Create a new project dialog, select ASP.NET Core Web Application > Next.
  3. In the Configure your new project dialog, enter MVCCallWebAPI for Project name.
  4. Select Create.
  5. In the Create a new ASP.NET Core web application dialog, select,
     
    1. .NET Core and ASP.NET Core 5.0 in the dropdowns.
    2. ASP.NET Core Web App (Model-View-Controller).
    3. Create

Build and run the app, you will see the following image shows the app,

Step 2: Reverse engineer Entity model from database (database first aproach for Entity)
We use a local Microsft SQL server, and the sample database pubs and its table stores as our database sample. We try to reverse engineer to get the table Stores into the project and make an entity model Store.
 
Click "Tools->NuGet Package Manager->Package Manager Console" as shown below i.e.


This is the reverse engineering command (when you run the command in PMC, you need to make it in one line),
    Scaffold-DbContext "Data Source=localhost;Initial Catalog=pubs;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False" Microsoft.EntityFrameworkCore.SqlServer   
    -OutputDir Models/DB   
    -Table dbo.stores  


Run the command in the PMC,

We got error message above that Microsoft.EntityFrameworkCore.Design is required, but not installed. Click "Tools->NuGet Package Manager->Manage NuGet Packages for Solution" as shown below,

Choose and install: Microsoft.EntityFrameworkCore.Design,

Run the PMC command again,

We got: Unable to find provider assembly 'Microsoft.EntityFrameworkCore.SqlServer', install it in the same way above from Manage NuGet Packages for Solution, and then reRun PMC command. This was successful and two classes are reverse engineered under Models/DB as shown below: pubsContext.cs and Store.cs

Step 3: Add Controller with View using Entity Framework
For adding controller using entity framework, we need to modify the reverse engineered classes pubsContext and Store.cs.
1. Modify the data connection
For the class pubsContext, we need to comment out the data connection part,

    //        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)  
    //        {  
    //            if (!optionsBuilder.IsConfigured)  
    //            {  
    //#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see http://go.microsoft.com/fwlink/?LinkId=723263.  
    //                optionsBuilder.UseSqlServer("Data Source=localhost;Initial Catalog=pubs;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False");  
    //            }  
    //        }  

and move the data connection string into file appsettings.json,
     {        
      "Logging": {        
        "LogLevel": {        
          "Default": "Information",        
          "Microsoft": "Warning",        
          "Microsoft.Hosting.Lifetime": "Information"        
        }        
      },        
            
      "ConnectionStrings": {        
        "DevConnection": "Data Source=localhost;Initial Catalog=pubs;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"        
      },        
          
      "AllowedHosts": "*"        
    }    


Register the database connection context into Class starup.cs inside ConfigureServices,
    public void ConfigureServices(IServiceCollection services)        
    {        
        // Register SQL database configuration context as services.         
        services.AddDbContext<pubsContext>(options =>        
        {        
            options.UseSqlServer(Configuration.GetConnectionString("DevConnection"));        
        });        
            
        services.AddControllersWithViews();        
    }    


Otherwise,  we could make a controller with view using this entity framework, and this would not work.
 
2. Modify the model
In class pubsContext, we can also comment out the data constrain part,
    //protected override void OnModelCreating(ModelBuilder modelBuilder)    
    //{    
    //    modelBuilder.HasAnnotation("Relational:Collation", "SQL_Latin1_General_CP1_CI_AS");    
        
    //    modelBuilder.Entity<Store>(entity =>    
    //    {    
    //        entity.HasKey(e => e.StorId)    
    //            .HasName("UPK_storeid");    
        
    //        entity.ToTable("stores");    
        
    //        entity.Property(e => e.StorId)    
    //            .HasMaxLength(4)    
    //            .IsUnicode(false)    
    //            .HasColumnName("stor_id")    
    //            .IsFixedLength(true);    
        
    //        entity.Property(e => e.City)    
    //            .HasMaxLength(20)    
    //            .IsUnicode(false)    
    //            .HasColumnName("city");    
        
    //        entity.Property(e => e.State)    
    //            .HasMaxLength(2)    
    //            .IsUnicode(false)    
    //            .HasColumnName("state")    
    //            .IsFixedLength(true);    
        
    //        entity.Property(e => e.StorAddress)    
    //            .HasMaxLength(40)    
    //            .IsUnicode(false)    
    //            .HasColumnName("stor_address");    
        
    //        entity.Property(e => e.StorName)    
    //            .HasMaxLength(40)    
    //            .IsUnicode(false)    
    //            .HasColumnName("stor_name");    
        
    //        entity.Property(e => e.Zip)    
    //            .HasMaxLength(5)    
    //            .IsUnicode(false)    
    //            .HasColumnName("zip")    
    //            .IsFixedLength(true);    
    //    });    
        
    //    OnModelCreatingPartial(modelBuilder);    
    //}    
        
    //partial void OnModelCreatingPartial(ModelBuilder modelBuilder);    


but, we need to modify the data model to make the table member names exactly the same as they are in database, such as StorId into Stor_Id, and add a  [Key] for primary key in database.
 
The class Store.cs, before,
    using System.ComponentModel.DataAnnotations;    
      
    #nullable disable    
        
    namespace MVCCallWebAPI.Models.DB    
    {    
        public partial class Store    
        {    
            public string StorId { get; set; }    
            public string StorName { get; set; }    
            public string StorAddress { get; set; }    
            public string City { get; set; }    
            public string State { get; set; }    
            public string Zip { get; set; }    
        }    
    }     


After
    using System.ComponentModel.DataAnnotations;    
      
    #nullable disable    
        
    namespace MVCCallWebAPI.Models.DB    
    {    
        public partial class Store    
        {    
            [Key]    
            public string Stor_Id { get; set; }    
            public string Stor_Name { get; set; }    
            public string Stor_Address { get; set; }    
            public string City { get; set; }    
            public string State { get; set; }    
            public string Zip { get; set; }    
        }    
    }    

The final class pubsContext will be,
    using Microsoft.EntityFrameworkCore;  
     
    #nullable disable  
      
    namespace MVCCallWebAPI.Models.DB  
    {  
        public partial class pubsContext : DbContext  
        {  
            public pubsContext()  
            {  
            }  
      
            public pubsContext(DbContextOptions<pubsContext> options)  
                : base(options)  
            {  
            }  
      
            public virtual DbSet<Store> Stores { get; set; }  
      
    //        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)  
    //        {  
    //            if (!optionsBuilder.IsConfigured)  
    //            {  
    //#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see http://go.microsoft.com/fwlink/?LinkId=723263.  
    //                optionsBuilder.UseSqlServer("Data Source=localhost;Initial Catalog=pubs;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False");  
    //            }  
    //        }  
      
            //protected override void OnModelCreating(ModelBuilder modelBuilder)  
            //{  
            //    modelBuilder.HasAnnotation("Relational:Collation", "SQL_Latin1_General_CP1_CI_AS");  
      
            //    modelBuilder.Entity<Store>(entity =>  
            //    {  
            //        entity.HasKey(e => e.StorId)  
            //            .HasName("UPK_storeid");  
      
            //        entity.ToTable("stores");  
      
            //        entity.Property(e => e.StorId)  
            //            .HasMaxLength(4)  
            //            .IsUnicode(false)  
            //            .HasColumnName("stor_id")  
            //            .IsFixedLength(true);  
      
            //        entity.Property(e => e.City)  
            //            .HasMaxLength(20)  
            //            .IsUnicode(false)  
            //            .HasColumnName("city");  
      
            //        entity.Property(e => e.State)  
            //            .HasMaxLength(2)  
            //            .IsUnicode(false)  
            //            .HasColumnName("state")  
            //            .IsFixedLength(true);  
      
            //        entity.Property(e => e.StorAddress)  
            //            .HasMaxLength(40)  
            //            .IsUnicode(false)  
            //            .HasColumnName("stor_address");  
      
            //        entity.Property(e => e.StorName)  
            //            .HasMaxLength(40)  
            //            .IsUnicode(false)  
            //            .HasColumnName("stor_name");  
      
            //        entity.Property(e => e.Zip)  
            //            .HasMaxLength(5)  
            //            .IsUnicode(false)  
            //            .HasColumnName("zip")  
            //            .IsFixedLength(true);  
            //    });  
      
            //    OnModelCreatingPartial(modelBuilder);  
            //}  
      
            //partial void OnModelCreatingPartial(ModelBuilder modelBuilder);  
        }  
    }


3. Add the controller
In Solution Explorer, right-click the Controllers folder > Add > New Scaffolded Item. Then, select MVC Controller with views, using Entity Framework > Add.

Complete the Add MVC Controller with Views, using Entity Framework dialog,

    Model class - Store(MVCCallWebAPI.Models.DB)
    Data context class - pubsContext (MVCCallWebAPI.Models.DB)
    Views - Keep the default of each option checked
    Controller name - Change the default StoresController to StoresMVCController
    Select Add

Visual Studio creates,
    A StroesMVC controller (Controllers/StoresMVCController.cs)
    Razor view files for Create, Delete, Details, Edit, and Index pages (Views/StoresMVC/*.cshtml)

The automatic creation of these files is known as scaffolding.

Step 4. Run and Test the app
Before we run the app, modify the header of the file: Views/Shared/_layout.cshtml Views, shown below, change the controller as StoreMVC and the app name as MVC app:
    <header>    
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">    
            <div class="container">    
                <a class="navbar-brand" asp-area="" asp-controller="StroeMVC" asp-action="Index">MVC app</a>    
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"    
                        aria-expanded="false" aria-label="Toggle navigation">    
                    <span class="navbar-toggler-icon"></span>    
                </button>    
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">    
                    <ul class="navbar-nav flex-grow-1">    
                        <li class="nav-item">    
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>    
                        </li>    
                        <li class="nav-item">    
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>    
                        </li>    
                    </ul>    
                </div>    
            </div>    
        </nav>    
    </header>     


Now, we run the app,

Click MVC app, we got the screen,


This is a MVC app that consumes the  database directly through entity framework.
 
B: Add Web API with Entity Framework Code First
This part will add a ASP.NET Core Web API into the app with Entity Framework code first approach.

    Step 1: Set up a new Database context
    Step 2: Work with a database using Entity Framework code first appoach.
    Step 3,:Scaffold API Controller with Action using Entity Framework
    Step 4: Add Swagger client for Web API
    Step 5: Run and Test app

At the end, you have an Web API built in a MVC app. The Web API is consumed by Swagger interface and can be consumed by any other interfaces, such as Postman.

Step 1: Set up a new Database Context
We make a new database context with the same model, Model/Store.cs, and different database, DB_Demo_API:
 
1. Create a new Database Context class, named DB_Demo_APIContext.cs,
    using Microsoft.EntityFrameworkCore;    
      
    #nullable disable    
        
    namespace MVCCallWebAPI.Models.DB    
    {    
        public partial class DB_Demo_APIContext : DbContext    
        {    
            public DB_Demo_APIContext()    
            {    
            }    
        
            public DB_Demo_APIContext(DbContextOptions<DB_Demo_APIContext> options)    
                : base(options)    
            {    
            }    
        
            public virtual DbSet<Store> Stores { get; set; }    
        
        }    
    }     

2. Add the new Connection in the appsettings.json file,
    {        
      "Logging": {        
        "LogLevel": {        
          "Default": "Information",        
          "Microsoft": "Warning",        
          "Microsoft.Hosting.Lifetime": "Information"        
        }        
      },        
            
      "ConnectionStrings": {        
        "DevConnection": "Data Source=localhost;Initial Catalog=pubs;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"        
      },        
            
      "ConnectionStrings": {        
        "DB_Demo_APIConnection": "Data Source=localhost;Initial Catalog=DB_Demo_API;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"        
      },        
            
      "AllowedHosts": "*"        
    }   


3. Register the database connection context into Class starup.cs inside ConfigureServices,
    public void ConfigureServices(IServiceCollection services)      
    {       
        // Register SQL database configuration context as services.       
        services.AddDbContext<pubsContext>(options =>      
        {  options.UseSqlServer(Configuration.GetConnectionString("DevConnection"));      
        });      
        services.AddDbContext<DB_Demo_APIContext>(options =>      
        {      
            options.UseSqlServer(Configuration.GetConnectionString("DB_Demo_APIConnection"));      
        });      
          
        services.AddControllersWithViews();      
    }     


Step 2: Work with a database using Entity Framework code first appoach.
Click "Tools->NuGet Package Manager->Package Manager Console"(See A-Step 2), and run the PMC command (make them in one line),
    Add-Migration   
    -Name initialMigration   
    -Context DB_Demo_APIContext     

We got two migration files under Migration folder,

Run PMC command
    Update-Database    
    -Name initialMigration     
    -Context DB_Demo_APIContext       


We got the database table Stores created in database DB_Demo_API

Step 3: Scaffold API Controller with Action using Entity Framework

    Right-click the Controllers folder.
    Select Add > New Scaffolded Item.
    Select API Controller with actions, using Entity Framework, and then select Add.

In the Add API Controller with actions, using Entity Framework dialog,

    Model class -Store(MVCCallWebAPI.Models.DB)
    Data context class - DB_Demo_APIContext (MVCCallWebAPI.Models.DB)
    Controller name - Change the default StoresController to StoresWebAPIController
    Select Add


The generated code,

    Marks the class with the [ApiController] attribute. This attribute indicates that the controller responds to web API requests.
    Uses DI to inject the database context (DB_Demo_APIContext) into the controller. The database context is used in each of the CRUD methods in the controller.

Step 4: Add Swagger client for Web API
Swagger (OpenAPI) is a language-agnostic specification for describing REST APIs. It allows both computers and humans to understand the capabilities of a REST API without direct access to the source code. Swagger UI offers a web-based UI that provides information about the service, using the generated OpenAPI specification.
 
If we created a new Web API project, the Swagger cient for Web API would be installed by default. In our current case, the Web API is created in a MVC module, so we need to install Swagger manually.
 
1. Install Swagger Client
Right-click the project in Solution Explorer > Manage NuGet Packages, search for Swagger


There are three main components to Swashbuckle (Swagger), we only need to install two of them: SwaggerGen and SwaggerUI, the Swagger would be included.
 
2.  Register Swagger Client in startup.json file
Add the Swagger generator to the services collection in the Startup.ConfigureServices method,
    // This method gets called by the runtime. Use this method to add services to the container.        
    public void ConfigureServices(IServiceCollection services)        
    {        
        // Register the Swagger generator, defining 1 or more Swagger documents        
        services.AddSwaggerGen(c =>        
        {        
            c.SwaggerDoc("v2", new OpenApiInfo { Title = "MVCCallWebAPI", Version = "v2" });        
        });        
        ......      
    }   


Enable the middleware for serving the generated JSON document and the Swagger UI, in the Startup.Configure method,
    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.        
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        
    {        
        // Enable middleware to serve generated Swagger as a JSON endpoint.        
        app.UseSwagger();        
            
        // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),        
        // specifying the Swagger JSON endpoint.        
        app.UseSwaggerUI(c =>        
        {        
            c.SwaggerEndpoint("/swagger/v2/swagger.json", "MVCCallWebAPI");        
        });        
        ......      
    }      


Now, we are almost ready to run the app.
 
Step 5: Run and Test the app
Before we run the app, modify the header of the file: Views/Shared/_layout.cshtml Views again, shown below,
    <header>        
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">        
            <div class="container">        
                <a class="navbar-brand" asp-area="" asp-controller="StoresMVC" asp-action="Index">MVC app</a>        
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"        
                        aria-expanded="false" aria-label="Toggle navigation">        
                    <span class="navbar-toggler-icon"></span>        
                </button>        
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">        
                    <ul class="navbar-nav flex-grow-1">        
                        <li class="nav-item">        
                            <a class="nav-link text-dark" asp-area="" asp-controller="Swagger" asp-action="Index">Web API</a>        
                        </li>        
                        <li class="nav-item">        
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>        
                        </li>        
                        <li class="nav-item">        
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>        
                        </li>        
                    </ul>        
                </div>        
            </div>        
        </nav>        
    </header>       


Now, we run the app,
 

Click Web API, we got the Swagger Client screen,



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