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 :: Implement Cascading Dropdown In ASP.NET Core MVC Application Using InMemory DB

clock May 17, 2023 10:15 by author Peter

Today, this article will discuss how we can design or develop any dependent or cascading dropdown control in Asp.net Core MVC Application. While developing any application using any language, sometimes we must define dropdown control that populates data from the backend part, i.e., from the database section. So, control directly fetches data from the database by using APIs and displays it in the dropdown control. But, sometimes, we need to implement the dependent dropdown control. It means the value of the dependent dropdown control depends on another. So, as per the selected value of the first dropdown control, we need to pass that value to the database side with the help of a parameter, and then as per that value, it will return the corresponding values to bind the second control. In this article, we will demonstrate this function with the help of the Asp.Net Core MVC Application.


Pre-Requisites
We must create a sample application using Asp.Net Core to demonstrate the functionality. For that purpose, we will use the .Net 7.0 framework. So, we need the below tools as a pre-requisite.
    Visual Studio 2022 Community Edition / Visual Studio Code
    .Net 7.0 SDK (only required if we use Visual Studio Code as Code Editor).

Also, we are not using any database tools for the database-related part. For the time-saving part, we are using the In-Memory database features of the Asp.Net Core application. We must use database tools like SQL, Oracle, MySQL, etc. In that case, we can need to replace the In-Memory database connection part with the actual database connection details.

In this example, we will use two models: Category and Product. Every product information is tagged with an existing category. So, finally, in the view part, once we select any Category value from the dropdown, it will populate related product items accordingly.
Steps to Develop Cascading Dropdown in Asp.Net Core MVC

Step 1
Open Visual Studio 2022 and click on Create New Project with the template "Asp.Net Core Web App (Model-View-Controller)."

Step 2
Then click on the Next Button and provide the Project Name.

Step 3
Then click on the Next Button and select .Net 7.0 as the Framework version. (If anyone is using VS 2019, then also select .Net 5.0 or .Net 6.0)

Step 6
Select the Model folder, create a new class file called Category.cs, and add the code below.
public class Category {
    public int Id {
        get;
        set;
    }
    public string Name {
        get;
        set;
    }
    public virtual List < Product > Products {
        get;
        set;
    }
}

Step 7
Again, add another new file called Product.cs and add the below code –
public class Product {
    public int Id {
        get;
        set;
    }
    public string Code {
        get;
        set;
    }
    [Required]
    public string Name {
        get;
        set;
    }
    [MaxLength(255)]
    public string ? Description {
        get;
        set;
    }
    public decimal Price {
        get;
        set;
    }
    public bool IsAvailable {
        get;
        set;
    }
    public int CategoryId {
        get;
        set;
    }
    [JsonIgnore]
    public virtual Category Category {
        get;
        set;
    }
}


Step 8

Now, we need to create the DBContext File. So, we need to add a new file called InMemoryDBContext.cs file and the below code in that file.
public class InMemoryDBContext: DbContext {
    public InMemoryDBContext(DbContextOptions < InMemoryDBContext > options): base(options) {}
    protected override void OnModelCreating(ModelBuilder modelBuilder) {
        modelBuilder.Entity < Category > ().HasMany(c => c.Products).WithOne(a => a.Category).HasForeignKey(a => a.CategoryId);
        modelBuilder.Seed();
    }
    public DbSet < Product > Products {
        get;
        set;
    }
    public DbSet < Category > Categories {
        get;
        set;
    }
}

Step 9
In the above code, we invoke the Seed() of the ModelBuilder. This method is responsible for initiating the base data related to the Category and Product. For that purpose, we have created a static call called ModelBuilderExtensions and implemented the Seed() method in that class with some sample data. So, we call the Category or Product list from the View Part; it populates the data from this list.

Step 10
After that, we need to open the Program.cs File and add the below code in that File.
builder.Services.AddDbContext<InMemoryDBContext>(options => options.UseInMemoryDatabase("Shop"));
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
    // options.SuppressModelStateInvalidFilter = true;
  }
);


Step 11

Now, we can perform the scaffold function of the Asp.Net Core MVC Application to generate the entire View & Controller layer related to the Category and Products. Once the scaffold files are created, we can execute the application and display just like below for both category and product parts.


 

Step 12
Now, open the Index.cshtml view under the Home folder. There add the below code to populate two different dropdown control related to the Category and Product list.
@{
    ViewData["Title"] = "Home Page";
    var baseurl = ViewBag.BaseUrl;
}

<div class="text-center">
    <h2>Cascading Dropdown Demo</h2>

    <div class="row form-group">
        <div class="col-md-2">
            <label asp-for="CategoryId" class="control-label"></label>
        </div>
        <div class="col-md-4">
            <select asp-for="CategoryId" class="form-control"
                    asp-items="ViewBag.CategoryData"
                    id="CategoryId"></select>
        </div>
        <div class="col-md-2">
            <label asp-for="ProductId" class="control-label"></label>
        </div>
        <div class="col-md-4">
            <select asp-for="ProductId" class="form-control" asp-items="ViewBag.ProductData" id="ddlProductId"></select>
        </div>
    </div>
</div>


Step 13
Now, open the HomeController.cs file under the controller folder and add the below code in the Index Action method. This code will fetch the Category and the Product list and return it as a view bag object. Initially, it does not produce any list value of the Product, as it will only populate if we pass any category id value to filter the product list.
public class HomeController: Controller {
    private readonly ILogger < HomeController > _logger;
    private readonly InMemoryDBContext _context;
    public HomeController(ILogger < HomeController > logger, InMemoryDBContext context) {
        _logger = logger;
        _context = context;
        _context.Database.EnsureCreated();
    }
    public IActionResult Index() {
        var _categories = _context.Categories.ToList();
        var _products = new List < Product > ();
        _categories.Add(new Category() {
            Id = 0, Name = "--Select Category--"
        });
        _products.Add(new Product() {
            Id = 0, Name = "--Select Product--"
        });
        ViewData["CategoryData"] = new SelectList(_categories.OrderBy(s => s.Id), "Id", "Name");
        ViewData["ProductData"] = new SelectList(_products.OrderBy(s => s.Id), "Id", "Name");
        string host = $ "{Request.Scheme}://{Request.Host}{Request.PathBase}/";
        ViewData["BaseUrl"] = host;
        return View();
    }
    public IActionResult Privacy() {
            return View();
        }
        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
    public IActionResult Error() {
        return View(new ErrorViewModel {
            RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier
        });
    }
}


Step 14
Now, we can run the application and check that the category dropdown already binds with the existing category data. But, the product dropdown does secure any data.

Step 15
We need to add a new action method to return the filtered product list as per the selected category id. This method accepts one input value called categoryId from the View part, and as per that categoryId, it will filter the product list and return the data in a JSON format. For that, open the ProductController.cs file and add the code below.
[HttpPost, ActionName("GetProductsByCategoryId")]
public JsonResult GetProductsByCategoryId(string categoryId) {
    int catId;
    List < Product > productLists = new List < Product > ();
    if (!string.IsNullOrEmpty(categoryId)) {
        catId = Convert.ToInt32(categoryId);
        productLists = _context.Products.Where(s => s.CategoryId.Equals(catId)).ToList();
    }
    return Json(productLists);
}

Step 16
We must consume the above action method from the view to retrieve the JSON data and bind it with the product dropdown. For that, we will take the help of JQuery code. Now, return to the Index.cshtml file under the home folder and add the below code there under script sections –
@section scripts
    {
    <script type="text/javascript">
        $(document).ready(function () {
            var a = 0;
        });
        function loadProduct(obj) {
            var value = obj.value;
            var url = "@baseurl";
            $.post(url + "Products/GetProductsByCategoryId", { categoryId: value }, function (data) {
                debugger;
                PopulateDropDown("#ddlProductId", data);
            });
        }
        function PopulateDropDown(dropDownId, list, selectedId) {
            $(dropDownId).empty();
            $(dropDownId).append("<option>--Please Product--</option>")
            $.each(list, function (index, row) {
                $(dropDownId).append("<option value='" + row.id + "'>" + row.name + "</option>")
            });
        }
    </script>
}


Step 17    
Now, invoke the loadProduct() method from the HTML part related to the Product dropdown. For that, change the code related to the product dropdown as below –
<select asp-for="CategoryId" class="form-control"
                   asp-items="ViewBag.CategoryData"
                   id="CategoryId" onchange="loadProduct(this)"></select>

Step 18
Now, run the application, select any category from the dropdown, and check related products populated within the product dropdown.


This article discusses cascading dropdown generation using the Asp.Net Core MVC application. Also, we discussed the steps related to implementing the In-Memory database concept. Any suggestions, feedback, or queries related to this article are appreciated.



ASP.NET MVC Hosting - HostForLIFEASP.NET :: Remote Validation in MVC

clock May 12, 2023 09:07 by author Peter

Hello everyone, in this post I'll describe how to integrate remote validation into MVC. Remote validation is the technique by which we verify particular data before publishing it to a server without posting the complete form's data. Let's look at a real-world example. In one of my projects, I had to verify that an email address didn't already exist in the database.

Remote validation was helpful in that regard because it allowed us to validate simply the user-supplied email address without submitting the rest of the data.Explanation in PracticeLet's create an MVC project and give it the appropriate name—for me, "TestingRemoteValidation"—then proceed. Let's create a model called UserModel once the project has been built. Its design will be as follows:
    public class UserModel  
    {
        [Required]
        public string UserName { get; set; }
        [Remote("CheckExistingEmail","Home",ErrorMessage = "Email already exists!")]
        public string UserEmailAddress { get; set; }
    }

Let's get some understanding of the remote attribute used, so the very first parameter “CheckExistingEmail” is the name of the action. The second parameter “Home” is referred to as controller so to validate the input for the UserEmailAddress the “CheckExistingEmail” action of the “Home” controller is called and the third parameter is the error message. Let's implement the “CheckExistingEmail” action result in our home controller.
    public ActionResult CheckExistingEmail(string UserEmailAddress)
    {
        bool ifEmailExist = false;
        try
        {
            ifEmailExist = UserEmailAddress.Equals("[email protected]") ? true : false;
            return Json(!ifEmailExist, JsonRequestBehavior.AllowGet);
        }
        catch (Exception ex)
        {
            return Json(false, JsonRequestBehavior.AllowGet);
        }
    }


For simplicity I am just validating the user input with a hard-coded value but we can call the database and determine whether or not the given input exists in the database.

Let's create the view using the defined “UserModel” and using the create scaffold template; the UI will look like:

We will get the following output if we use “[email protected]” as UserEmailAddress:



ASP.NET MVC Hosting - HostForLIFEASP.NET :: Three Different Ways to Upload a File in ASP.NET MVC

clock May 5, 2023 08:41 by author Peter

There are a few things that all web applications have in common. File Upload is one of the most common things that all web applications have. This is used to move data, upload large amounts of data, upload pictures, videos, etc.


I've mostly seen three ways to share a file while working on different web apps and products, especially in ASP.NET MVC. We will look at it in depth.

1. File Control with Html.BeginForm
When we submit the form, we can post our selected file to the server and read it. Below is the code to bind the File control
@Html.TextBoxFor(model =>
       model.DocumentFile, new {
                type = "file",
                @id = "documentFile"

})


And the type of DocumentFile property is as below.
public HttpPostedFileBase DocumentFile { get; set; }

To save this file, we created one folder and added the path of the folder in the config. We are accessing the folder location as below
var path = ConfigurationManager.AppSettings["CustomerDocuments"].ToString();


Now we need to save the file in the folder and insert the path of the file in the database

if (objGroup.GSTDocumentFile != null)
{
     using (Stream inputStream = objGroup.GSTDocumentFile.InputStream)
     {
         byte[] data;
         using (MemoryStream ms = new MemoryStream())
         {
             inputStream.CopyTo(ms);
             data = ms.ToArray();
         }
         System.IO.File.WriteAllBytes(Path.Combine(ClientFolder, objGroup.GSTDocumentFile.FileName), data);
     }
        objGroup.Document = objGroup.DocumentFile.FileName;
}


2. File upload using AJAX - Base64 as a parameter
When we select a file using file upload on the browser, we need to fire an event to capture the file like below
document.getElementById("uploadfile").addEventListener('change', handleFileSelect, false);

Using this event listener, we execute the function on selection of file and capture the file as below
function handleFileSelect(evt) {

     const id = evt.currentTarget.id;
     const f = evt.target.files[0];
     const Name = evt.target.files[0].name;
     const reader = new FileReader();

     reader.onload = (function(theFile) {

          return function(e) {

               const binaryData = e.target.result;
               const base64String = window.btoa(binaryData);

               $("#uploadDocBase64").val(base64String);
               $("#uploadFileName").val(Name);

          };

     })(f);

     reader.readAsBinaryString(f);

}


Here we capture the  file as well as the file name, and using AJAX, we can send this file to the server
try {

  const response = await fetch('@Url.Action("FileUpload", "Upload")', {
    method: 'POST',
    body: JSON.stringify({ fileStr: $("#uploadDocBase64").val() }),
    headers: {
      'Content-Type': 'application/json; charset=utf-8'
    }
  });

  const result = await response.json();

  alert('Success');

} catch (error) {

  alert('Failure');
  console.error(error);

}


System.IO.File.WriteAllBytes(path, Convert.FromBase64String(Convert.ToString(fileStr)));

3. File Upload using Fetch with FileData

There is an issue with option no 2. Big files are not getting uploaded as it is going in the parameter. To overcome this, we can add all the parameters and files in fileData and upload a file.
try {

  const fileData = new FormData();

  fileData.append("File", $("#uploadDocBase64").val());

  const response = await fetch('@Url.Action("UpdateStatusAndDiscussion", "Discussion")', {
    method: 'POST',
    body: fileData,
  });

  if (response.ok) {
    alert("Success");
  } else {
    alert("Failure");
  }

} catch (error) {
  console.error(error);
}


Now you can capture the file in the controller
byte[] imageBytes = Convert.FromBase64String(File);
MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length);
ms.Write(imageBytes, 0, imageBytes.Length);
path = HttpContext.Current.Server.MapPath("~/FileUpload/" + _GroupName + "/" + DoneFileName);
FileStream fileNew = new FileStream(path, FileMode.Create, FileAccess.Write);
ms.WriteTo(fileNew);
fileNew.Close();
ms.Close();


These are the ways to upload files to the server using ASP.NET MVC.




ASP.NET MVC Hosting - HostForLIFEASP.NET :: How to consume multiple GET API in one view in MVC?

clock April 17, 2023 09:17 by author Peter

In this article, we'll look at how to use MVC to consume several GET APIs in a single view. We'll go over how to create a Model to store the data, a Controller action to contact the APIs and fill the Model, and a View to display the data.


The Controller in the Model-View-Controller (MVC) architecture processes data, receives user input, and returns views. It is typical for web app developers to need several APIs to retrieve data for a single view. In this situation, we may design a Controller action that queries several APIs and then sends a ViewModel to the View, which can render the retrieved information understandable.

The following steps must be followed to use multiple GET APIs in a single MVC view.

Step 1
The initial step is to create a model to store the information collected from the APIs. AclassThe Model's properties must align with the information the APIs have returned. A new or existing class can be created to represent this Model.
public class ProjectCol
    {
        public List<master> master { get; set; }
        public List<Project> projects { get; set; }
        public List<User> users { get; set; }

    }
public class master
    {
            public int Id { get; set; }
            public string RoleName { get; set; }
    }
 public class Project
    {
        public int Id { get; set; }

        public string ProjectName { get; set; }
    }
public class User
    {
        public string UserId { get; set; }
        public string Name { get; set; }
    }
Step2
Creating a Controller action to make API calls and add data to the Model comes next. GET queries to the appropriate APIs can be sent this way using the HTTPClient or WebClient libraries.
public async Task<ActionResult> ProjectTest(ProjectCol projectallot)
 {
     string url = configuration.GetValue<string>("Projectapi:BaseApi");
     ProjectCol projectAllotment = new ProjectCol();

     List<master> _master = new List<master>();
     var baseurl = ServicesEndPonit.usermanagement.Getallrole(url);
     HttpResponseMessage Res = await httpClient.GetAsync(baseurl);
     if (Res.IsSuccessStatusCode)
     {
         var data = Res.Content.ReadAsStringAsync().Result;
         _master = JsonConvert.DeserializeObject<List<master>>(data);
     }
     List<User> user = new List<User>();
     var baseurl_ = ServicesEndPonit.usermanagement.GetUsers(url);
     HttpResponseMessage Res_ = await httpClient.GetAsync(baseurl_);
     if (Res_.IsSuccessStatusCode)
     {
         var data_ = Res_.Content.ReadAsStringAsync().Result;
         user = JsonConvert.DeserializeObject<List<User>>(data_);
     }
     List<Project> projects = new List<Project>();
     var baseurl_pro = ServicesEndPonit.ProjectManagement.GetProjects(url);
     HttpResponseMessage Res_pro = await httpClient.GetAsync(baseurl_pro);
     if (Res_pro.IsSuccessStatusCode)
     {
         var data_pro = Res_pro.Content.ReadAsStringAsync().Result;
         projects = JsonConvert.DeserializeObject<List<Project>>(data_pro);
     }
     projectAllotment.projects = projects;
     projectAllotment.users = user;
     projectAllotment.master = _master;
     return View(projectAllotment);
 }


Step 3
We can provide the Model to the view after populating it with data from the APIs. The data from each API model can then be displayed in the view using the Model attributes. The view's Razor syntax can be used to accomplish this.
<div class="row">
    <div class="col-sm-4">
        <label> User</label>
        <select class="form-select" required name="AssignedTo" id="ddlAllmember">
            <option value="hidden">Select AssginTo </option>
            @foreach (var item in Model.users)
            {
                <option value="@item.UserId">@item.Name</option>
            }

        </select>
</div>
    <div class="col-sm-4">
        <label>Job Role</label>
        <select class="form-select" required name="RoleID" id="ddlJobroleId">
            <option value="hidden">Select Job role </option>
            @foreach (var item in Model.master)
            {
                <option value="@item.Id">@item.RoleName</option>
            }
        </select>
    </div>
    <div class="col-sm-4">
        <label>Project </label>
        <select class="form-select" required name="ProjectID" id="ddlProjectName">
            <option value="hidden">Select ProjectCode </option>
            @foreach (var item in Model.projects)
            {
                <option value="@item.Id">@item.ProjectName</option>
            }
        </select>
    </div>

</div>

MVC can make consuming several GET APIs in a single view difficult. Still, it is possible by defining API models, creating a Model, using the APIs in the controller, and finally providing the Model to the view.

Follow C# Corner to learn more new and amazing things about  ASP.NET MVC or to explore more technologies. If you have any queries/suggestions on the article, please leave your questions and thoughts in the comment section below. Thanks for reading, and I hope you like it.



ASP.NET MVC Hosting - HostForLIFEASP.NET :: Authentication And Authorization In ASP.NET Core MVC Using Cookie

clock April 11, 2023 10:25 by author Peter

Authentication and Authorization are two major aspects while thinking about securing your application. Security is the main concern of modern applications because anyone can steal your data if it is not secured. So, if you are going to create an application where the data security is a primary concern, then think about Authentication and Authorization.


Authentication is the process to validate an anonymous user based on some credentials and Authorization process happens just after that and grants resources to this validated user. So, we can say, it's two-step validating process before providing the access of the resources or data.

We have many techniques to validate the users, like Windows Authentication, JWT Authentication, and Cookie Authentication etc. Today, we will learn how to implement and make ASP.NET Core MVC applications more secure using Cookie-based authentication and authorization. So, let's start the demonstration and create a fresh ASP.NET Core MVC project. You can refer to the following for the step by step process of creating an ASP.NET Core MVC application.

Be sure that while creating the project, your template should be Web Application (Model-View-Controller) and change the authentication as ‘No Authentication’.
You can download the code from here.

Here, you can choose the inbuilt Authentication functionality instead of ‘No Authentication’ and it will provide the readymade code. But we are choosing ‘No Authentication’ here because we are going to add our own Cookie-based authentication functionality in this demo and you will learn how to implement the Authentication and Authorization system from scratch.


We are choosing MVC template because we would like to see some Login and Logout functionality on UI along with Authentication and Authorization using Cookies. Now, click OK and it will take a few seconds and the project will be ready. Run it for checking if everything is working fine or not. Once everything is OK, you are ready to go.

Let’s move to the starting point of the ASP.NET Core application file which is “Startup.cs” where we configure the setting for the application like configuring the required services and configuring the middleware services etc. So, implementing the Authentication features, first, we have to add the authentication and then use it. So, let’s move to Startup.cs’s ConfigureService method and add the authentication feature using the following line of code, it will be just above services.AddMvc().
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();  

Now move to Configure in the startup.cs method and use the authentication features using the following line of code, it will be just above  routing.
app.UseAuthentication();  

Following is the whole code for adding the Authentication and using it.
    using Microsoft.AspNetCore.Authentication.Cookies;  
    using Microsoft.AspNetCore.Builder;  
    using Microsoft.AspNetCore.Hosting;  
    using Microsoft.AspNetCore.Http;  
    using Microsoft.AspNetCore.Mvc;  
    using Microsoft.Extensions.Configuration;  
    using Microsoft.Extensions.DependencyInjection;  
      
    namespace CookieDemo  
    {  
        public class Startup  
        {  
            public Startup(IConfiguration configuration)  
            {  
                Configuration = configuration;  
            }  
      
            public IConfiguration Configuration { get; }  
      
            // This method gets called by the runtime. Use this method to add services to the container.  
            public void ConfigureServices(IServiceCollection services)  
            {  
                services.Configure<CookiePolicyOptions>(options =>  
                {  
                    // This lambda determines whether user consent for non-essential cookies is needed for a given request.  
                    options.CheckConsentNeeded = context => true;  
                    options.MinimumSameSitePolicy = SameSiteMode.None;  
                });  
      
                services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();  
                services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);  
            }  
      
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.  
            public void Configure(IApplicationBuilder app, IHostingEnvironment env)  
            {  
                if (env.IsDevelopment())  
                {  
                    app.UseDeveloperExceptionPage();  
                }  
                else  
                {  
                    app.UseExceptionHandler("/Home/Error");  
                }  
      
                app.UseStaticFiles();  
                app.UseCookiePolicy();  
                app.UseAuthentication();  
                app.UseMvc(routes =>  
                {  
                    routes.MapRoute(  
                        name: "default",  
                        template: "{controller=Home}/{action=Index}/{id?}");  
                });  
            }  
        }  
    }  

We can implement Authentication through Login feature. In most of the applications today, Authorization is decided internally based on your role. So, now we are going to create account login and logout feature, so just create one more controller as ‘AccountController.cs’ inside the controllers folder and add two action methods, one for rendering the Login View and  the other one for posting user credentials data for logging in to the system. Here is the code for AccountController where we have implemented Login functionality.
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Security.Claims;  
    using System.Threading.Tasks;  
    using Microsoft.AspNetCore.Authentication;  
    using Microsoft.AspNetCore.Authentication.Cookies;  
    using Microsoft.AspNetCore.Mvc;  
      
    namespace CookieDemo.Controllers  
    {  
        public class AccountController : Controller  
        {  
            public IActionResult Login()  
            {  
                return View();  
            }  
      
            [HttpPost]  
            public IActionResult Login(string userName, string password)  
            {  
                if(!string.IsNullOrEmpty(userName) && string.IsNullOrEmpty(password))  
                {  
                    return RedirectToAction("Login");  
                }  
      
                //Check the user name and password  
                //Here can be implemented checking logic from the database  
      
                if(userName=="Admin" && password == "password"){  
      
                    //Create the identity for the user  
                    var identity = new ClaimsIdentity(new[] {  
                        new Claim(ClaimTypes.Name, userName)  
                    }, CookieAuthenticationDefaults.AuthenticationScheme);  
      
                    var principal = new ClaimsPrincipal(identity);  
      
                    var login = HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);  
      
                    return RedirectToAction("Index", "Home");  
                }  
      
                return View();  
            }  
        }  
    }  


The first login action method is rendering the UI for login page and once you fill the data required for Login as username and password then the second action method as Login will work and send the Post request to the server.

In this method, first, we will check whether username and password should not be empty then we will validate the username and password. Here, in this demonstration, we are checking the username and password with some dummy data. You can implement database login instead of this.

After validating the user information, if everything is correct then we create Identity for that user and create the cookie information for it. Based on this principal data, we try to Sign In using a generic function called "SignInAsync" and if everything goes in the right direction then we redirect to the Home page.

Now, let's create the Login view page from where we can give the functionality to the user to enter the username and password. So, right click on the Login action method and add view without a model. It will automatically create the Account folder inside the Views under that will create “login.cshtml” file. Just open it and create a container and add a form tag along with two textboxes for entering the username and password. Apart from this, create two separate buttons as “Submit” and “Reset”. Once you fill the data and click on the submit button, it will call to Login action method defined in Account Controller using POST call. So, modify the code of “login.cshtml” as follows.
    @{  
        ViewData["Title"] = "Login";  
    }  
      
    <div class="container">  
        <div class="row">          
            <div class="col-md-3">  
                <h2><strong>Login Page </strong></h2><br />  
                <form asp-action="login" method="post">  
                    <div class="form-group">  
                        <label>User Name</label>  
                        <input type="text" class="form-control" id="userName" name="userName" placeholder="Enter user name">  
                    </div>  
                    <div class="form-group">  
                        <label>Password</label>  
                        <input type="password" class="form-control" name="password" id="password" placeholder="Password">  
                    </div>  
                    <div class="form-check">  
                        <button class="btn btn-info" type="reset">Reset</button>  
                        <button type="submit" class="btn btn-primary">Submit</button>  
                    </div>  
                </form>  
            </div>  
        </div>  
    </div>  


So far we have implemented the Cookie-based Authentication functionality in Asp.Net Core MVC project. But what about Authorization. Authorization means, providing access to the authenticated user to access a resource based on role.

So, let's first understand how we can implement the Authorization in Asp.Net Core MVC. For now, if you will try to access the HOME page without sign in, you can access it. So, let’s prevent the anonymous user from accessing the HOME page directly, if someone wants to access the HOME page then they should have to go through the Authentication process and then they will be able to access it.

So, to accomplish this, let’s open the Home Controller and put the [Authorize] attribute just above to controller. You can place it at action level but here we would like to block the whole home controller functionality and if we want to access, just go and log in. So, just do something like below.
    using CookieDemo.Models;  
    using Microsoft.AspNetCore.Authorization;  
    using Microsoft.AspNetCore.Mvc;  
    using System.Diagnostics;  
      
    namespace CookieDemo.Controllers  
    {  
      
        [Authorize]  
        public class HomeController : Controller  
        {          
            public IActionResult Index()  
            {  
                return View();  
            }  
      
            public IActionResult About()  
            {  
                ViewData["Message"] = "Your application description page.";  
      
                return View();  
            }  
      
            public IActionResult Contact()  
            {  
                ViewData["Message"] = "Your contact page.";  
      
                return View();  
            }  
      
            public IActionResult Privacy()  
            {  
                return View();  
            }  
      
            [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]  
            public IActionResult Error()  
            {  
                return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });  
            }  
        }  
    }  


Note
Be sure you have cleared all cookies which have been  created based on your previous login. If you will not do this, you will be accessing the HOME page, it is because authenticated user cookie is available in browser memory.

So, let's check how it works. Run the application and try to access the Home page. You will see here that your application automatically redirects to Login page. Now let's try to provide the user information as username = "Admin" and password =" password". Once you will pass the correct credentials and login then you will redirect to HOME page. So, let'sadd the feature that shows the logged in username along with a logout button. If you click to the log out button, your cookie value will be deleted and you will redirect to login page.

So, let's open the Account Controller and add the following logout action method.
    [HttpPost]  
    public IActionResult Logout()  
    {  
          var login = HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);  
          return RedirectToAction("Login");  
    }  


And now open the Index.cshtml file from the Home folder inside the Views and modify the code as follows. Here, first of all, we are trying to show the Logged In username using @User.Identity.Name and apart from this adding a link for logout.
    @{  
        ViewData["Title"] = "Home Page";  
    }  
      
    <div class="container">  
        <div class="row">  
            <div class="col-md-12">  
                <h2><strong>Home Page </strong></h2><br /><br />  
                Hello @User.Identity.Name  
                <a asp-action="logout" asp-controller="account">  
                    Logout  
                </a>  
                <br />  
                <br />  
                <h4>Welcome to Asp.Net Core Authentication and Authorization Demo!!</h4>  
            </div>  
        </div>  
    </div>  


So far, we are able to understand how to implement Authentication in Asp.Net Core MVC and how to implement Authorization and give access to validate the users. Now, let's understand how to work with multiple roles. Here we are doing everything manually with some static value, but you can change the logic and connect to the database for validating the user. So, just modify the Login method as follows where we are providing two different kinds of roles; one is Admin role and another is User role. Based on these roles, we will provide access to some of the pages.
    [HttpPost]  
    public IActionResult Login(string userName, string password)  
    {  
        if (!string.IsNullOrEmpty(userName) && string.IsNullOrEmpty(password))  
        {  
            return RedirectToAction("Login");  
        }  
      
        //Check the user name and password  
        //Here can be implemented checking logic from the database  
        ClaimsIdentity identity = null;  
        bool isAuthenticated = false;  
      
        if (userName == "Admin" && password == "password")  
        {  
      
            //Create the identity for the user  
            identity = new ClaimsIdentity(new[] {  
                        new Claim(ClaimTypes.Name, userName),  
                        new Claim(ClaimTypes.Role, "Admin")  
                    }, CookieAuthenticationDefaults.AuthenticationScheme);  
      
            isAuthenticated = true;  
        }  
      
        if (userName == "Peter" && password == "password")  
        {  
            //Create the identity for the user  
            identity = new ClaimsIdentity(new[] {  
                        new Claim(ClaimTypes.Name, userName),  
                        new Claim(ClaimTypes.Role, "User")  
                    }, CookieAuthenticationDefaults.AuthenticationScheme);  
      
            isAuthenticated = true;  
        }  
      
        if (isAuthenticated)  
        {  
            var principal = new ClaimsPrincipal(identity);  
      
            var login = HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);  
      
            return RedirectToAction("Index", "Home");  
        }  
        return View();  
    }  


Now let's move to HomeController and remove the [Authorize] attribute from the class level and put it in action level as follows. Here we have two different action methods which point to two different views. One is pointing to Index view and another one is pointing to the Setting page. Index page can be accessible to both type of roles, either it is Admin or User but the Setting page can be accessed only by Admin role.
    public class HomeController : Controller  
    {  
            [Authorize(Roles ="Admin, User")]  
            public IActionResult Index()  
            {  
                return View();  
            }  
      
            [Authorize(Roles ="Admin")]  
            public IActionResult Setting()  
            {  
                return View();  
      
            }  


Now modify the Index.cshtml file and add one thing as Role, just modify the code as follows.
    @{  
        ViewData["Title"] = "Setting Page";  
    }  
      
    <div class="container">  
        <div class="row">  
            <div class="col-md-12">  
                <h2><strong>Setting Page </strong></h2><br /><br />  
                Hello @User.Identity.Name !, Role @User.FindFirst(claim=>claim.Type==System.Security.Claims.ClaimTypes.Role)?.Value  
                <a asp-action="logout" asp-controller="account">  
                    Logout  
                </a>  
                <br />  
                <br />  
                <h4>Admin role user can only access this page!!</h4>  
            </div>  
        </div>  
    </div>  


Now, we have added everything and it's time to run the application. So, just press F5 and it will run your application. First, go to "Login" page and login with "User" role.

Once you will log in as a User role, definitely you will be redirected to the home page because the home page is accessible to both types  the roles.

Now, let's try to access the settings page, here you will get some Access Denied error. It is because "User" role member does not allow you to access the settings page. By default, you will get the following error as per the browser. But you can customize your error and page as well. It totally depends on you.

Now, let log out of the application for the "User" role and try to log in for Admin role. As follows, you can see, we are able to access the home page.

But let try to access the setting page for "Admin" role and yes, you will be accessed the setting page.

Lastly, let me show how you can see the cookie information. For this demo, I am using the Microsoft Edge browser, you can use any other as per your choice. But cookie information saves almost in the same place for every browser. So, just go to Network tab and then Cookie tab. Here you can see all the listed Cookies.

 



ASP.NET MVC Hosting - HostForLIFEASP.NET :: Introducing Mobile Site in MVC and jQuery Mobile

clock March 29, 2023 10:14 by author Peter

As you know there are various types of emulators available for viewing applications. We can use the iPhone and Windows Phone simulators for browsing the application. You can open the website on a phone that is so much more satisfying than a Desktop.


In that context, when you create the MVC 4 application you can use a Mobile template to design the application. Here, I am using Visual Studio 2013 and a MVC 5 project template to design the application. We'll use the jQuery Mobile application for displaying it in the phones and tablets.

Let's create an application on Visual Studio using MVC 5 Project template and perform some CRUD operations and add jQuery Mobile and ViewSwitcher. I am using the iPhone simulator to browse the application.

Creating CRUD Operations
Step 1: Add a model class named Cricketer and add the following code:
    public enum Grade  
    {  
        A,B,C  
    }  
    public class Cricketer  
    {  
        public int ID { get; set; }  
        public string Name { get; set; }  
        public string Team { get; set; }  
        public Grade Grade { get; set; }  
    }  
    public class CricketerDbContext : DbContext  
    {  
        public DbSet<Cricketer> Cricketers { get; set; }  
    }


In the code above, we've created an Enum property and we'll add the Enum support to the View in this article later.

Step 2: Scaffold a New Controller


Step 3: Unfortunately scaffolding does not do the Enums in the Create.cshtml and Edit.cshtml pages. You can see in the following screenshot:

Step 4: So we need to update it using the following highlighted code:
    <div class="form-group">  
        @Html.LabelFor(model => model.Grade, new { @class = "control-label col-md-2" })  
        <div class="col-md-10">  
            @Html.EnumDropDownListFor(model => model.Grade)  
            @Html.ValidationMessageFor(model => model.Grade)  
        </div>  
    </div>  


Step 4: Ok. Now it's time to run the application and perform the CRUD operations.

Adding Mobile Support
You can develop it while creating the MVC 4 application with the Mobile Template but you can add the jQuery Mobile along with the MVC 5 application. You can simply have it from the NuGet Pacakges or entering the following command in the Pacakge Manager Console:

Install-Package jQuery.Mopbile.MVC

This package will add various things such as:
    A ViewSwitcher partial view and supporting Controller
    Basic _Layout.Mobile.cshtml and supporting CSS
    Newly added BundleMobileConfig.cs

Note: You can use jQuery in any mobile framework.

Now you need to modify the Global.asax file with the following highlighted code:
    protected void Application_Start()  
    {  
        AreaRegistration.RegisterAllAreas();  
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);  
        RouteConfig.RegisterRoutes(RouteTable.Routes);  
        BundleConfig.RegisterBundles(BundleTable.Bundles);  
        BundleMobileConfig.RegisterBundles(BundleTable.Bundles);  
    }


When you run the application on the iPhone simulator as in the following:

The following screenshot will open:


Now change the table in the Index.cshml page with the following code:
    <ul data-role="listview" data-filter="true" class="my_class_list">  
    @foreach (var item in Model)  
    {  
        <li>  
            <a href="@Url.Action("Details", new {item.ID})">  
                <h3>@Html.DisplayFor(modelItem => item.Name)</h3>  
                <p>@Html.DisplayFor(modelItem => item.Team) - @Html.DisplayFor(modelItem => item.Grade) Grade</p>  
            </a>  
        </li>  
    }  
    </ul>

Now just refresh the page.




ASP.NET MVC Hosting - HostForLIFEASP.NET :: Working Process of Validations in MVC

clock March 21, 2023 08:19 by author Peter

In this article, I am introducing the use of Data Annotations in MVC 5 using Microsoft Visual Studio 2013 Preview. As you know I previously deployed a MVC Application in which I used various types of techniques like Adding View, Adding Model, Login, CRUD Operations, Code Migration, Searching. These are very necessary in MVC Applications but when you develop applications, it is necessary to apply validations on that app. So, here you will learn how to validate an app in MVC 5.


In that context, validations are applied in MVC applications by the following assembly:
using System.ComponentModel.DataAnnotations;  

Here I will tell you that I am creating validation logic in my Cricketers Model. When a user creates or edits any cricketer. You can see the validation on my page in the following image:

Don't Repeat Yourself
Whenever you design an ASP.NET MVC application, Don't Repeat Yourself (DRY) is the basic assumption that you need to use. This makes your code clean, reduces the amount of code and easy to maintain because the more code you write with fewer errors the more your code functions better.

In ASP.NET MVC applications, validations are defined in the Model Class and applied all over the application. The Entity Framework Code First approach and MVC are the pillar for the validation.

So, let's begin to take advantage of Data Annotation of MVC in your application with the following criteria.

Use of Data Annotation
You need to add some logic for validation in your MVC application. For adding let's start step-by-step.

Step 1: Open Cricketers.cs from the Solution Explorer.

Step 2: Add the following assembly reference at the top of your Cricketers.cs file:
using System.ComponentModel.DataAnnotations;  

Step 3: Change your code with the following code (depends on your logic):
    using System.ComponentModel.DataAnnotations;  
    using System.Data.Entity;  
    namespace MvcCricket.Models  
    {  
        public class Cricketer  
        {  
            public int ID { get; set; }  
            [Required]  
            [StringLength(50, MinimumLength=4)]  
            public string Name { get; set; }  
            [Required]  
            [Range(1,500)]  
            public int ODI { get; set; }  
            [Required]  
            [Range(1,200)]  
            public int Test { get; set; }  
            [Required]  
            public string Grade { get; set; }  
        }  
    }  

In the code above, you can see that the Required attribute is used in each property. That means that the user needs to enter the value in it. In the Name property the StringLength attribute defines the min and max length of the Name. In the ODI and TEST property the Range attribute is defined to min and max length.

Step 4: Open a Library Package Manager Console and write the following command in it:
add-migration DataAnnotations

After pressing Enter:

Step 5: Again write the following command in the Library Package Manager Console:
update-database

What does Visual Studio do? Visual Studio opens the DataAnnotations.cs file and you will see the DbMigration class is the base class of DataAnnotations. There are two methods in it. In the Up() and Down(), you will see the updated database schema. Check it out with the following code:
    namespace MvcCricket.Migrations  
    {  
        using System;  
        using System.Data.Entity.Migrations;  
        public partial class DataAnnotations : DbMigration  
        {  
            public override void Up()  
            {  
                AlterColumn("dbo.Cricketers", "Name", c => c.String(nullable: false, maxLength: 50));  
                AlterColumn("dbo.Cricketers", "Grade", c => c.String(nullable: false));  
            }  
            public override void Down()  
            {  
                AlterColumn("dbo.Cricketers", "Grade", c => c.String());  
                AlterColumn("dbo.Cricketers", "Name", c => c.String());  
            }  
        }  
    }  


You can see in the code above that the Name and Grade property are no longer nullable. You need to enter values in it. Code First ensures that the validation rules you specify on a model class are enforced before the application saves changes in the database.

Step 6: Debug your application and open the Cricketers folder.

Click on Create New Link to create some new cricketer.

That's It. If you want to know the working process of validation process then you to notice my following paragraph.

Validation Process
    public ActionResult Create()  
    {  
        return View();  
    }  
    //  
    // POST: /Cricketers/Create  
    [HttpPost]  
    [ValidateAntiForgeryToken]  
    public ActionResult Create(Cricketer cricketer)  
    {  
        if (ModelState.IsValid)  
       {  
            db.Cricketers.Add(cricketer);  
            db.SaveChanges();  
            return RedirectToAction("Index");  
        }  
        return View(cricketer);  
    }  


In the code above when the form opens in the browser the HTTP GET method is called and in the Create action method initiates. The second method HttpPost handles the post method. This method checks that the validation errors in the form and if the object finds the errors then the Create method re-creates the form, otherwise the method saves the data in the database. In here, the form is not posted to the server, because the validation error occurs in the client-side. You can also disable your JavaScript to see the error using a breakpoint.

The following is an example of that.

In Internet Explorer

 

In Google Chrome


Validation Summary
You can also see the changes in your Create.cshtml file when you apply the Validation in your application. Check it out in my file:
    @using (Html.BeginForm())  
    {  
        @Html.AntiForgeryToken()  
        @Html.ValidationSummary(true)  
        <fieldset class="form-horizontal">  
            <legend>Cricketer</legend>  
            <div class="control-group">  
                @Html.LabelFor(model => model.Name, new { @class = "control-label" })  
                         <div class="controls">  
                               @Html.EditorFor(model => model.Name)  
                               @Html.ValidationMessageFor(model => model.Name, null, new { @class = "help-inline" })  
                         </div>  
                  </div>  
            <div class="control-group">  
                @Html.LabelFor(model => model.ODI, new { @class = "control-label" })  
                         <div class="controls">  
                               @Html.EditorFor(model => model.ODI)  
                               @Html.ValidationMessageFor(model => model.ODI, null, new { @class = "help-inline" })  
                         </div>  
                  </div>  
            <div class="control-group">  
                @Html.LabelFor(model => model.Test, new { @class = "control-label" })  
                         <div class="controls">  
                               @Html.EditorFor(model => model.Test)  
                               @Html.ValidationMessageFor(model => model.Test, null, new { @class = "help-inline" })  
                         </div>  
                  </div>  
            <div class="control-group">  
                @Html.LabelFor(model => model.Grade, new { @class = "control-label" })  
                <div class="controls">  
                    @Html.EditorFor(model=>model.Grade)  
                    @Html.ValidationMessageFor(model => model.Grade, null, new { @class = "help-inline" })  
                </div>  
            </div>  
            <div class="form-actions no-color">  
                <input type="submit" value="Create" class="btn" />  
            </div>  
        </fieldset>  
    }   


Summary
So far this article will help you to learn to validate your MVC Application. You can also see the procedure and working procedure of Validation in my app. So just go for it.



ASP.NET MVC Hosting - HostForLIFEASP.NET :: Generate Images In ASP.NET Core MVC Using OpenAI

clock March 16, 2023 09:50 by author Peter

Using DALL-E in an ASP.NET Core application involves integrating the OpenAI API into your code. We can generate multiple images based on the given text using DALL-E generate image API endpoint. First, you must develop an OpenAI API key to authorize API use. In this article, I will explain how you can use DALL-E API in the ASP.NET Core MVC application to generate images based on the text.


Agenda for the Article,
    What is OpenAI?
    What is DALL-E?
    How to get OpenAI API Key
    Generating Image In ASP.NET Core MVC

What is OpenAI?
OpenAI is an artificial intelligence research lab that works to develop and grow AI in different fields like medicine, education, sports, information technology, etc. It was founded in 2015. OpenAI conducts research in various areas of AI, including machine learning, natural language processing, robotics, and computer vision. The organization has developed several groundbreaking AI models, including GPT-3, DALL-E, and CLIP. In this article, I will explain the use of the DALL-E. I have also written an article on GPT-3. To know more, please refer to this article.

What is DALL-E?

DALL-E is an artificial intelligence (AI) program developed by OpenAI that generates images from textual descriptions using a transformer-based language model. DALL-E is named after the famous artist Salvador Dali. The program can create highly detailed and complex images of objects, animals, and scenes that do not exist in the real world but also in the real world. It works by learning from a dataset of images and their associated textual descriptions, allowing it to generate fictional and realistic images based on the given textual input. DALL-E is a significant breakthrough in AI image generation and has the potential to revolutionize various industries, including advertising, gaming, and e-commerce.

Generating OpenAI API Key
You need to authorize the API endpoint by passing the API key. To generate an OpenAI API key, follow these steps:

Signup for an OpenAI account. Go to the OpenAI website and create a new account.

Confirm your email address.
Now, Log in to your account and navigate to the 'View API keys' section as given below.

Now, click on 'Create new secret key' as given below.


Store your API key in a secure location, as it will be required to access the OpenAI APIs. You can copy the key and save it for future use. OpenAI has usage and resource limitations for its API, so be sure to check its documentation here for details on usage and pricing.

Generating Image In ASP.NET Core MVC

To generate images in the ASP.NET Core MVC application using DALL-E, you need to follow the below-given steps:
    First, create an ASP.NET Core MVC project. To know more about creating a project, please refer here.
    Add your API key in the appsettings.json file as given below

    //demo key
    "OpenAI_API_KEY": "sk-cF8Dv3n2YtUXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"


Add the below-given code for the UI in your Index.cshtml file inside Views>Home>Index.cshtml
<h1 class="display-4">Image Generator</h1>
<!--Image info-->
<input type="text" class="form-control" id="txt" style="width:400px;" placeholder="Image Description" />
<br />
<!--Image Size-->
<select id="size">
    <option selected>256x256</option>
    <option>512x512</option>
</select>
<!--Images Required-->
<input type="number" value="1" placeholder="Images Required" id="quantity" />
<!--Generate button-->
<button id="generate">
    Generate
</button>
<br />
<!--Display image here-->
<div id="Imagedisplay" class="col-md-14 row">
</div>


In the above-given code, you have added a UI for the home page to enter some basic details required for the image, like the information about the image, the number of images required, and the size of the image.

Now you will add a model class ImageInfo.cs inside the Models folder as given below.
public class ImageInfo {
    public string ? ImageText {
        get;
        set;
    }
}
public class RequiredImage {
    public string ? prompt {
        get;
        set;
    }
    public short ? n {
        get;
        set;
    }
    public string ? size {
        get;
        set;
    }
}
public class ImageUrls {
    public string ? url {
        get;
        set;
    }
}
// response handling
public class ResponseModel {
    public long created {
        get;
        set;
    }
    public List < ImageUrls > ? data {
        get;
        set;
    }
}

In the above-given code, You have added ResponseModel class for handling the response and RequiredImage class for the input data about the required image.

Now you will add a controller method inside HomeController.cs as given below.
[HttpPost]
public async Task < IActionResult > GenerateImage([FromBody] RequiredImage obj) {
    string imglink = string.Empty;
    var response = new ResponseModel();
    using(var client = new HttpClient()) {
        client.DefaultRequestHeaders.Clear();
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", APIKEY);
        var Message = await client.PostAsync("https://api.openai.com/v1/images/generations", new StringContent(JsonConvert.SerializeObject(obj), Encoding.UTF8, "application/json"));
        if (Message.IsSuccessStatusCode) {
            var content = await Message.Content.ReadAsStringAsync();
            response = JsonConvert.DeserializeObject < ResponseModel > (content);
            imglink = resp.data[0].url.ToString();
        }
    }
    return Json(response);
}


You have added a post-call with the DALL-E API key in the above given code. You have to pass the API key shown above.

The final step is to display the image on the UI using javascript. So you have to add the below-given code inside wwwroot>js>site.js.
$(document).ready(() => {
    $('#generate').click(function() {
        var info = {};
        info.n = parseInt($('#quantity').val());
        info.prompt = $('#txt').val();
        info.size = $('#size').find(":selected").val();
        $.ajax({
            url: '/Home/GenerateImage',
            method: 'post',
            contentType: 'application/json',
            data: JSON.stringify(info)
        }).done(function(data) {
            $.each(data.data, function() {
                $('#Imagedisplay').append('<div class="col-md-5" style="padding-top:12px">' + '<img class="p-12" src = "' + this.url + '"/>' + '</div>');
            });
        });
    });
});


Output

Conclusion
OpenAI provides us with lots and lots of use for artificial intelligence. AI has become a part of our daily life nowadays. ChatGPT and DALL-E are all advanced and great examples of AI. To generate an image, you need two things. First, the OpenAI APOI key and second DALL-E API endpoint. Pass the API key in the header and freely use that endpoint.

Thank You, and Stay Tuned for More.



ASP.NET MVC Hosting - HostForLIFEASP.NET :: Repository Design Pattern In ASP.NET MVC

clock March 14, 2023 08:30 by author Peter

Why Design Pattern?
Traditionally, what do we do? We access our database directly, without using any middle layer or Data Access Layer (DAL).

Do you think this is a good approach? No, it's not! Here is why.
 
The tight coupling of the database logic in the business logic makes applications complex, tough to test, and tough to extend further. Direct access to the data in the business logic causes many problems like difficulty in completing the Unit Test of the business logic, disability to test business logic without the dependencies of external systems like a database, and a duplicate data access code throughout the business layer. I hope we now know why we need a design pattern. There are many types of design patterns but in today’s article, we will discuss repository design pattern.
 
What is a Repository Design Pattern?
By definition, the Repository Design Pattern in C# mediates between the domain and the data mapping layers using a collection-like interface for accessing the domain objects. Repository Design Pattern separates the data access logic and maps it to the entities in the business logic. It works with the domain entities and performs data access logic. In the Repository pattern, the domain entities, the data access logic, and the business logic talk to each other using interfaces. It hides the details of data access from the business logic.
 
Advantages of Repository Design Pattern

  • Testing controllers becomes easy because the testing framework need not run against the actual database access code.
  • Repository Design Pattern separates the actual database, queries and other data access logic from the rest of the application.
  • Business logic can access the data object without having knowledge of the underlying data access architecture.
  • Business logic is not aware of whether the application is using LINQ to SQL or ADO.NET. In the future, underlying data sources or architecture can be changed without affecting the business logic.
  • Caching strategy for the data source can be centralized.
  • Centralizing the data access logic, so code maintainability is easier

Non-Generics Repository Design Pattern Source Code
Generics Repository Design Pattern Source Code

Implementation
Let’s do it practically and see how it implements. We will take a very basic example of implementation. I have attached the code file that you can download from the above link. I try to do it step by step and explained each step so that you can understand better. I full try to make it simple, clear and understandable.
 
Step 1
Let’s create a simple database (BasicDb) containing a single table with the name of Product_Table. The Backup and Script file is attached simply download it and restore it in SQL. You can choose any one file for restoration.
 
Step 2
Create the Asp.Net MVC Project with the name of (Repository Design Pattern) screenshots are below.

Select MVC

Step 3
Create an Entity Framework to give the model name DataContext.

Select Entity framework designer from the database.

Select Database

Change name to (DataContext) it is optional you can keep as it is,

Select Table

Step 4
Create a Folder in the model folder with the name (DAL) where we will implement our repository.

Step 5
Create an Interface Class (IProductRepository.cs)

Paste this Code to IProductRepository.cs,
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Text;  
    using System.Threading.Tasks;  
      
    namespace Repositiory_Pattern.Models.DAL  
    {  
        interface IProductRepository  
        {  
            IEnumerable<Product_Table> GetProducts();  
            Product_Table GetProductById(int ProductId);  
            void InsertProduct(Product_Table product_);  
            void UpdateProduct(Product_Table product_);  
            void DeleteProduct(int ProductId);  
            void SaveChanges();  
        }  
    }


IProductRepository.cs

Step 6
Create a class in the DAL folder (ProductRepository.cs) This will be child class and will implement all the methods of (IProductRepository.cs) class. Paste this Code
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Web;  
      
    namespace Repositiory_Pattern.Models.DAL  
    {  
        public class ProductRepository:IProductRepository  
        {  
            private DataContext _dataContext;  
            public ProductRepository(DataContext dataContext)  
            {  
                this._dataContext = dataContext;  
            }  
            public void DeleteProduct(int ProductId)  
            {  
                Product_Table product_ = _dataContext.Product_Table.Find(ProductId);  
                _dataContext.Product_Table.Remove(product_);  
            }  
            public Product_Table GetProductById(int ProductId)  
            {  
                return _dataContext.Product_Table.Find(ProductId);  
            }  
            public IEnumerable<Product_Table> GetProducts()  
            {  
                return _dataContext.Product_Table.ToList();  
            }  
            public void InsertProduct(Product_Table product_)  
            {  
                _dataContext.Product_Table.Add(product_);  
            }  
            public void SaveChanges()  
            {  
                _dataContext.SaveChanges();  
            }  
            public void UpdateProduct(Product_Table product_)  
            {  
             _dataContext.Entry(product_).State = System.Data.Entity.EntityState.Modified;  
            }  
        }  
    }

ProductRepository.cs

Step 7
Now just go to our built-in Home Controller and paste this code.
    using Repositiory_Pattern.Models;  
    using Repositiory_Pattern.Models.DAL;  
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Web;  
    using System.Web.Mvc;  
      
    namespace Repositiory_Pattern.Controllers  
    {  
        public class HomeController : Controller  
        {  
            private IProductRepository _productRepository;  
            public HomeController()  
            {  
                this._productRepository = new ProductRepository(new DataContext());  
            }  
            public ActionResult Index()  
            {  
                return View(_productRepository.GetProducts());  
            }       
            public ActionResult Create()  
            {  
                return View(new Product_Table());  
            }  
            [HttpPost]  
            public ActionResult Create(Product_Table product)  
            {  
                _productRepository.InsertProduct(product);  
                _productRepository.SaveChanges();  
                return RedirectToAction("Index");  
            }              
            public ActionResult Update(int Id)  
            {  
                return View(_productRepository.GetProductById(Id));  
            }  
            [HttpPost]  
            public ActionResult Update(Product_Table product)  
            {  
                _productRepository.UpdateProduct(product);  
                _productRepository.SaveChanges();  
                return RedirectToAction("Index");  
            }              
            public ActionResult Delete(int Id)  
            {  
                _productRepository.DeleteProduct(Id);  
                _productRepository.SaveChanges();  
                return RedirectToAction("Index");  
            }  
        }  
    }


HomeController.cs


Step 8
Now create the views Index, Create and Update. Just right click on the method name.
 
Index.cshtml

Create.cshtml


Update.cshtml

Step 9
Open the Index view and change the action name Edit to Update and save.

Step 10
Now just run and see the result in the browser.

In this project, we have performed CRUD operations using the Repository design pattern. We have created a single interface (IProductRepository.cs) and implemented all their methods in (ProductRepository.cs). Now if we have multiple entities or models then will we make an interface for each entity? No
 
We will not do this whereas we will make a single Generic (IModelRepository.cs) and (ModelRepository.cs) if we have multiple models we will use only a single interface and their single implementation class. The Generic Repository Project code I have attached so you can download it from the above mention link. If you have any queries about the problem you face please comment below I will answer.



ASP.NET MVC Hosting - HostForLIFEASP.NET :: Using MVC 6 And AngularJS 2 With .NET Core

clock March 8, 2023 07:22 by author Peter

Overview on ASP.NET

Let’s differentiate both.

.NET Framework

  • Developed and run on Windows platform only.
  • Built on the .NET Framework runtime.
  • Supported (MVC, Web API & SignalR) Dependency Injection (DI).
  • MVC & Web API Controller are separated.

.Net Core

  • Open Source.
  • Developed & run on Cross Platform.
  • Built on the .NET Core runtime & also on .NET Framework.
  • Facility of dynamic compilation.
  • Built in Dependency Injection (DI).
  • MVC & Web API Controller are unified, Inherited from same base class.
  • Smart tooling (Bower, NPM, Grunt & Gulp).
  • Command-line tools.


Start with .NET Core 1.0
Let’s create a new project with Visual Studio 2015 > File > New > Project.

Choose empty template and click OK.


Visual Studio will create a new project of ASP.NET Core empty project.

We will now explore all initial files one by one.

Explore Initial Template

Those marked from Solution Explorer are going to be explored, one by one.

First of all, we know about program.cs file. Let’s concentrate on it.

Program.cs: Here, we have sample piece of code. Let’s get explanation.
    namespace CoreMVCAngular  
    {  
        public class Program   
        {  
            public static void Main(string[] args) {  
                var host = new WebHostBuilder().UseKestrel().UseContentRoot(Directory.GetCurrentDirectory()).UseIISIntegration().UseStartup < Startup > ().Build();  
                host.Run();  
            }  
        }  
    }  


.UseKestrel() : Define the Web Server. ASP.NET Core supports hosting in IIS and IIS Express.

HTTP servers
    Microsoft.AspNetCore.Server.Kestrel (cross-platform)
    Microsoft.AspNetCore.Server.WebListener (Windows-only)

.UseContentRoot(Directory.GetCurrentDirectory()) : Application base path that specifies the path to the root directory of the Application.
.UseIISIntegration() : For hosting in IIS and IIS Express.
.UseStartup<Startup>() : Specifies the Startup class.
.Build() : Build the IWebHost, which will host the app & manage incoming HTTP requests.

Startup.cs
This is the entry point of every .NET Core Application. It provides services, that the Application required.
    namespace CoreMVCAngular   
    {  
        public class Startup   
        {  
            // This method gets called by the runtime. Use this method to add services to the container.  
            // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940  
            public void ConfigureServices(IServiceCollection services) {}  
                // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.  
            public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) {}  
        }  
    }  


As you can see, there are two methods; one is ConfigureServices & another is Configure. In Configure method, three parameters are specified.

IApplicationBuilder defines a class, which provides the mechanisms to configure an Application's request.

We can add MVC (middleware) to the request pipeline by using “Use” extension method. Later, we will use it.
ConfigureServices is an extension method, which is configured to use the several services.

Project.json: This is where our Application dependencies are listed i.e by name & version. This file also manages runtime, compilation settings.

Dependencies: All Application dependencies can add new dependencies, if required, intellisense will help up to include with the name & version.

After saving changes, it will automatically restore the dependencies from NuGet.


Here, the code snippet is changed.
    "dependencies": {  
    "Microsoft.NETCore.App": {  
    "version": "1.0.0",  
    "type": "platform"  
    },  
    "Microsoft.AspNetCore.Diagnostics": "1.0.0",  
      
    "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",  
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.0",  
    "Microsoft.Extensions.Logging.Console": "1.0.0",  
    "Microsoft.AspNetCore.Mvc": "1.0.0"  
    },  


To uninstall, go to Solution explorer > right click on package > Uninstall package.


Tools: This section manages and lists command line tools. We can see IISIntegration.Tools is added by default, which is a tool that contains dotnet publish iis command for publishing the Application on IIS.
    "tools": {  
    "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final"  
    },  


Frameworks: As we can see, initially our app is running on the .NET Core platform by default with the runtime.
    “netcoreapp1 .0”.  
    "frameworks": {  
        "netcoreapp1.0": {  
            "imports": ["dotnet5.6", "portable-net45+win8"]  
        }  
    },
 

Build Options: Options, which are passed to the compiler while building the Application.
    "buildOptions": {  
        "emitEntryPoint": true,  
        "preserveCompilationContext": true  
    },  


RuntimeOptions: Manage Server garbage collection at Application runtime.
    "runtimeOptions": {  
        "configProperties": {  
            "System.GC.Server": true  
        }  
    },  


PublishOptions: This defines the file/folder to include/exclude to/from the output folder, while publishing the Application.
    "publishOptions": {  
        "include": ["wwwroot", "web.config"]  
    },  


Scripts: Scripts is an object type, which specifies that scripts run during building or publishing the Application.
    "scripts": {  
        "postpublish": ["dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%"]  
    }  


Add MVC6
It’s time to add MVC6. In .NET Core 1.0 MVC & Web API are unified, and become a single class, which inherits from the same base class.

Let’s add MVC Service to our Application. Open project.json to add new dependencies in it. In dependencies section, add two dependencies.
    "Microsoft.AspNetCore.Mvc": "1.0.0",
    "Microsoft.AspNetCore.StaticFiles": "1.0.0"


Click Save.

It will start restoring the packages automatically.


Now let’s add MVC (midleware) to request pipeline in Config method at startup class.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) {  
        loggerFactory.AddConsole();  
        if (env.IsDevelopment()) {  
            app.UseDeveloperExceptionPage();  
        }  
        //app.UseStaticFiles();  
        app.UseMvc(routes => {  
            routes.MapRoute(name: "default", template: "{controller=Home}/{action=Index}/{id?}");  
        });  
    }  


In ConfigureServices method, we need to add framework Service. We have added services.AddMvc();
    public void ConfigureServices(IServiceCollection services) {  
        services.AddMvc();  
    }  

MVC Folder Structure

Let’s add MVC folder structure to our sample Application. We have added view files in the views folder & MVC controller in Controllers folder like old MVC Application.

Here, you may notice that there is a new file in the views folder “_ViewImports.cshtml”. This file is responsible for setting up the namespaces, which can be accessed by the views in the project, which was previously done by the Web.config file in the views folder.

We are almost done. Let’s modify our view content with welcome message. Now, run the Application. You can see welcome message appears in the home page.

Output

AngularJS2
AngularJS2 is a modern Client end JavaScript Framework for the Application development. This JavaScript framework is totally new & written, based on TypeScript.

We will follow the steps, given below, to learn, how we install it to our Application,
    Manage Client-side Dependencies
    Use Package Manager (NPM).
    Use Task Runner.
    Bootstrapping using Type Script.

Client-side Dependencies: We need to add a JSON config file for Node Package Manager(NPM). Click add > New Item > Client- Side > npm Configuration File and click OK.


Open our newly added npm config file and modify the initial settings.

Package.json
    {  
        "version": "1.0.0",  
        "name": "asp.net",  
        "private": true,  
        "Dependencies": {  
            "angular2": "2.0.0-beta.9",  
            "systemjs": "0.19.24",  
            "es6-shim": "^0.33.3",  
            "rxjs": "5.0.0-beta.2"  
        },  
        "devDependencies": {  
            "gulp": "3.8.11",  
            "gulp-concat": "2.5.2",  
            "gulp-cssmin": "0.1.7",  
            "gulp-uglify": "1.2.0",  
            "rimraf": "2.2.8"  
        }  
    }  

In the dependencies section, we need to add AngularJS2 with other dependencies and they are for:
    Es6-shim is a library, which provides compatibility on old environment.
    Rxjs provides more modular file structure in a variety of formats.
    SystemJS enables System.import TypeScript files directly.

As you can see, there are two different type objects; one is dependencies, which are used for the production purposes & the other one is devDependencies for development related things, like gulp is to run different tasks.

Click save. It will restore automatically. Here, we have all our required packages in the Dependencies section.


In this application we have added another package manager called Bower, Click add > New Item > Client- Side > Bower Configuration File then click Ok.

Comparing with NPM,
Bower:
    Manage html, css, js component
    Load minimal resources
    Load with flat dependencies

NPM:
    Install dependencies recursively
    Load nested dependencies
    Manage NodeJS module

Open the config file then add required dependencies in dependencies secction with specific version.

Save the JSON file after edit, it will automatically restore that package in our project. Here you can see we have added Jquery & Bootstrap package with Bower package manager.

Now, let’s add a gulp configuration file to run the task. Click Add > New Item > Client-Side. Select gulp JSON file to include.

 

Gulp.json
    /*
    This file in the main entry point for defining Gulp tasks and using Gulp plugins.
    Click here to learn more. http://go.microsoft.com/fwlink/?LinkId=518007
    */  
    "use strict";  
    var gulp = require("gulp");  
    var root_path = {  
        webroot: "./wwwroot/"  
    };  
    //library source  
    root_path.nmSrc = "./node_modules/";  
    //library destination  
    root_path.package_lib = root_path.webroot + "lib-npm/";  
    gulp.task("copy-systemjs", function() {  
        return gulp.src(root_path.nmSrc + '/systemjs/dist/**/*.*', {  
            base: root_path.nmSrc + '/systemjs/dist/'  
        }).pipe(gulp.dest(root_path.package_lib + '/systemjs/'));  
    });  
    gulp.task("copy-angular2", function() {  
        return gulp.src(root_path.nmSrc + '/angular2/bundles/**/*.js', {  
            base: root_path.nmSrc + '/angular2/bundles/'  
        }).pipe(gulp.dest(root_path.package_lib + '/angular2/'));  
    });  
    gulp.task("copy-es6-shim", function() {  
        return gulp.src(root_path.nmSrc + '/es6-shim/es6-sh*', {  
            base: root_path.nmSrc + '/es6-shim/'  
        }).pipe(gulp.dest(root_path.package_lib + '/es6-shim/'));  
    });  
    gulp.task("copy-rxjs", function() {  
        return gulp.src(root_path.nmSrc + '/rxjs/bundles/*.*', {  
            base: root_path.nmSrc + '/rxjs/bundles/'  
        }).pipe(gulp.dest(root_path.package_lib + '/rxjs/'));  
    });  
    gulp.task("copy-all", ["copy-rxjs", 'copy-angular2', 'copy-systemjs', 'copy-es6-shim']);  


To run the task, right click on Gulp.json file to reload.

Right click on copy-all & click run.

Task run & finish.

In Solution Explorer, all the required packages are copied. We also need to put the type definitions for es6-shim(typing folder), without this, it will cause error - "Cannot find name 'Promise'".

Bootstrapping with TypeScript

tsConfig.json
    {  
        "compilerOptions": {  
            "noImplicitAny": false,  
            "noEmitOnError": true,  
            "removeComments": false,  
            "sourceMap": true,  
            "target": "es5",  
            //add this to compile app component  
            "emitDecoratorMetadata": true,  
            "experimentalDecorators": true,  
            "module": "system",  
            "moduleResolution": "node"  
        },  
        "exclude": ["node_modules", "wwwroot/lib"]  
    }  


noImplicitAny : Raise an error on the expressions and declarations with an implied ‘any’ type.
noEmitOnError : Do not emit outputs, if any errors were reported.
Target : Specify ECMAScript target version: ‘es5’ (default), ‘es5’, or ‘es6’.
experimentalDecorators : Enables an experimental support for ES7 decorators.

Create an app folder for .ts file in wwwroot folder.


In Solution Explorer, you may add the files, given below.

In main.ts code snippet, bootstrap AngularJS with importing the component.

    import {bootstrap} from 'angular2/platform/browser';  
    import {AppComponent} from './app.component';  
    import {enableProdMode} from 'angular2/core';  
      
    enableProdMode();  
    bootstrap(AppComponent);  


Component: imports the Component function from Angular 2 library; use of import, app component class can be imported from other component.
import {Component} from 'angular2/core';

    @Component({  
        selector: 'core-app',  
        template: '<h3>Welcome to .NET Core 1.0 + MVC6 + Angular 2</h3>'  
    })  
    export class AppComponent {}  


MVC View: It’s time to update our layout & linkup the library.


Now, we will add the reference to our layout page.
    <!DOCTYPE html>  
    <html>  
      
    <head>  
        <meta name="viewport" content="width=device-width" />  
        <title>@ViewBag.Title</title>  
        <script src="~/lib-npm/es6-shim/es6-shim.js"></script>  
        <script src="~/lib-npm/angular2/angular2-polyfills.js"></script>  
        <script src="~/lib-npm/systemjs/system.src.js"></script>  
        <script src="~/lib-npm/rxjs/Rx.js"></script>  
        <script src="~/lib-npm/angular2/angular2.js"></script>  
    </head>  
      
    <body>  
        <div> @RenderBody() </div> @RenderSection("scripts", required: false) </body>  
      
    </html> Index.cshtml @{ ViewData["Title"] = "Home Page"; }  
    <core-app>  
        <div>  
            <p><img src="~/img/ajax_small.gif" /> Please wait ...</p>  
        </div>  
    </core-app> @section Scripts {  
    <script>  
        System.config({  
            packages: {  
                'app': {  
                    defaultExtension: 'js'  
                }  
            },  
        });  
        System.import('app/main').then(null, console.error.bind(console));  
    </script> }  


One more thing to do is to enable the static file serving. Add this line to startup config method.
app.UseStaticFiles();

Build & run application

Finally, build & run the Application.

Here, we can see our app is working with AngularJS2.



About HostForLIFE

HostForLIFE is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes.

We have offered the latest Windows 2019 Hosting, ASP.NET 5 Hosting, ASP.NET MVC 6 Hosting and SQL 2019 Hosting.


Tag cloud

Sign in