European ASP.NET MVC 4 and MVC 5 Hosting

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

ASP.NET MVC Hosting - HostForLIFEASP.NET :: Dependency Injection & EF Migrations in ASP.NET MVC with Autofac

clock October 31, 2024 07:13 by author Peter

This post will demonstrate how to integrate Entity Framework for database operations, including migration setup, and use Autofac to create Dependency Injection (DI) in an ASP.NET MVC application. Code modularity, testability, and maintainability are all enhanced by this method.

Configuring Dependency Injection with Autofac
1. Install the Autofac packages first.
To install Autofac and its integration package for MVC, launch the Package Manager Console and execute the subsequent commands.

Install-Package Autofac
Install-Package Autofac.Mvc5

Step 2. Configure Autofac
Open Global.asax.cs and configure Autofac in the Application_Start method.
using Autofac;
using Autofac.Integration.Mvc;
using System.Reflection;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using WebApplication2.Data;
using WebApplication2.IRepository;
using WebApplication2.Service;
namespace WebApplication2
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            var builder = new ContainerBuilder();
            // Register MVC controllers
            builder.RegisterControllers(Assembly.GetExecutingAssembly());
            // Register DbContext for DI
            builder.RegisterType<MyDbContext>().AsSelf().InstancePerRequest();
            // Register your services here
            builder.RegisterType<ProductService>().As<IProductService>();
            // Build the Autofac container
            var container = builder.Build();
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
            // Regular MVC application start
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }
}


Implementing Entity Framework and Migrations

Step 1. Install Entity Framework
Run the following command in the Package Manager Console to install Entity Framework:
Install-Package EntityFramework

Step 2. Create MyDbContext

In the WebApplication2.Data namespace, create a class named MyDbContext to represent your database context:

Create Model Class for Product.
using System.ComponentModel.DataAnnotations;
namespace WebApplication2.Models
{
    public class Product
    {
        [Key]
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
    }
}

Step 2. Create MyDbContext

In the WebApplication2.Data namespace, create a class named MyDbContext to represent your database context:
using System.Data.Entity;
using WebApplication2.Models;
namespace WebApplication2.Data
{
    public class MyDbContext : DbContext
    {
        public MyDbContext() : base("SqlServerConnection")
        {

        }
        // Define your entities here
        public DbSet<Product> Products { get; set; }
    }
}

Step 3. Enable Migrations

In the Package Manager Console, run the following command to enable migrations.
Enable-Migrations

Step 4. Create Initial Migration
Create an initial migration based on your current model.
Add-Migration InitialCreate

Step 5. Update Database

Apply the migration to the database:
Update-Database

Step 6. Add Connection String

Add a connection string for MyDbContext in the Web.config file.
<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  https://go.microsoft.com/fwlink/?LinkId=301880
  -->
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <connectionStrings>
    <add name="SqlServerConnection" connectionString="Server=MUD\SQLEXPRESS2022;Database=DIAndMigInNetFrameWord;User Id=sa;Password=123456;" providerName="System.Data.SqlClient" />
  </connectionStrings>
  <appSettings>
    <add key="webpages:Version" value="3.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.8" />
    <httpRuntime targetFramework="4.8" />
  </system.web>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Antlr3.Runtime" publicKeyToken="eb42632606e9261f" />
        <bindingRedirect oldVersion="0.0.0.0-3.5.0.2" newVersion="3.5.0.2" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Web.Infrastructure" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" />
        <bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-1.6.5135.21930" newVersion="1.6.5135.21930" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-5.2.9.0" newVersion="5.2.9.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-8.0.0.1" newVersion="8.0.0.1" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Autofac" publicKeyToken="17863af14b0044da" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-8.1.1.0" newVersion="8.1.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Bcl.AsyncInterfaces" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=&quot;Web&quot; /optionInfer+" />
    </compilers>
  </system.codedom>
  <entityFramework>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
      <!-- Removed SQLite and Npgsql providers -->
    </providers>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
  </entityFramework>
  <system.data>
    <DbProviderFactories>
      <remove invariant="System.Data.SQLite.EF6" />
      <remove invariant="System.Data.SQLite" />
      <remove invariant="Npgsql" />
      <add name="SQL Server" invariant="System.Data.SqlClient" description=".NET Framework Data Provider for SQL Server" type="System.Data.SqlClient.SqlClientFactory, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    </DbProviderFactories>
  </system.data>
</configuration>


Creating the Service and Repository Layers

Step 1. Create IProductService Interface

In the WebApplication2.IRepository namespace defines an interface for the product service.
using System.Collections.Generic;
using WebApplication2.Models;
namespace WebApplication2.IRepository
{
    public interface IProductService
    {
        IEnumerable<Product> GetAllProducts();
        void AddProduct(Product product);
    }
}

Step 2. Implement ProductService
In the WebApplication2.Service namespace, implement the ProductService class.
using System.Collections.Generic;
using System.Linq;
using WebApplication2.Data;
using WebApplication2.IRepository;
using WebApplication2.Models;
namespace WebApplication2.Service
{
    public class ProductService : IProductService
    {
        private readonly MyDbContext _context;
        public ProductService(MyDbContext context)
        {
            _context = context;
        }
        public IEnumerable<Product> GetAllProducts()
        {
            return _context.Products.ToList();
        }
        public void AddProduct(Product product)
        {
            _context.Products.Add(product);
            _context.SaveChanges();
        }
    }
}


Step 3. Create the Product Model
In the WebApplication2.Data namespace, create a Product model class.
using System.ComponentModel.DataAnnotations;
namespace WebApplication2.Models
{
    public class Product
    {
        [Key]
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
    }
}


Creating the MVC Controller
Create a controller to handle requests related to products.

Step 1. Create ProductController

In the Controllers folder, create a ProductController
using System.Web.Mvc;
using WebApplication2.IRepository;
using WebApplication2.Models;
namespace WebApplication2.Controllers
{
    public class ProductController : Controller
    {
        private readonly IProductService _productService;
        public ProductController(IProductService productService)
        {
            _productService = productService;
        }
        public ActionResult Index()
        {
            var products = _productService.GetAllProducts();
            return View(products);
        }
        [HttpGet]
        public ActionResult Create()
        {
            return View();
        }
        [HttpPost]
        public ActionResult Create(Product product)
        {
            if (ModelState.IsValid)
            {
                _productService.AddProduct(product);
                return RedirectToAction("Index");
            }
            return View(product);
        }
    }
}


Step 2. Create the View
In the Views/Product folder, create a view named Index. cshtml.
@model IEnumerable<WebApplication2.Models.Product>
@{
    ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Name)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Price)
        </th>
        <th></th>
    </tr>
@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Name)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Price)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
            @Html.ActionLink("Details", "Details", new { id=item.Id }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.Id })
        </td>
    </tr>
}
</table>


Step 3. Create the View

In the Views/Product folder, create a view named Create. cshtml.
@model WebApplication2.Models.Product
@{
    ViewBag.Title = "View";
}
<h2>View</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.Name, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Name, "", 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", "Index")
</div>
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}


Step 3. Create the View
Add the controller and Actions link in Layout Files.
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - My ASP.NET Application</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
</head>
<body>
    <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-dark bg-dark">
        <div class="container">
            @Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
            <button type="button" class="navbar-toggler" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" title="Toggle navigation" aria-controls="navbarSupportedContent"
                    aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse d-sm-inline-flex justify-content-between">
                <ul class="navbar-nav flex-grow-1">
                    <li>@Html.ActionLink("Home", "Index", "Home", new { area = "" }, new { @class = "nav-link" })</li>
                    <li>@Html.ActionLink("About", "About", "Home", new { area = "" }, new { @class = "nav-link" })</li>
                    <li>@Html.ActionLink("Contact", "Contact", "Home", new { area = "" }, new { @class = "nav-link" })</li>
                    <li>@Html.ActionLink("Product", "Index", "Product", new { area = "" }, new { @class = "nav-link" })</li>
                </ul>
            </div>
        </div>
    </nav>
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; @DateTime.Now.Year - My ASP.NET Application</p>
        </footer>
    </div>

    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @RenderSection("scripts", required: false)
</body>
</html>


Database Creation
After doing all of this, just run the migration.

Create Initial Migration
After enabling migrations, generate the initial migration based on your current model:
Add-Migration InitialCreate

This command creates a migration class in the Migrations folder that defines the initial schema for your database based on the Product model and the MyDbContext.

Update Database
Now, apply the migration to the database with the following command.
Update-Database

This command will create the database and tables defined in your MyDbContext. If your connection string is set up correctly, the database will be created in your SQL Server instance.

Running the Application

  • Run the application in Visual Studio.
  • Navigate to http://localhost:8081/Product/Index
  • You should see the products displayed in a table.

Output


 

Conclusion
In this article, we successfully implemented Dependency Injection using Autofac and integrated Entity Framework for data access in an ASP.NET MVC application. This setup allows for better separation of concerns, making the application easier to maintain and test. By following these steps, you can extend this architecture to accommodate more complex business logic, additional services, and different data operations as needed. Happy coding!



ASP.NET MVC Hosting - HostForLIFE.eu :: Introduction to Model View Control (MVC) Pattern using C#

clock October 25, 2024 08:16 by author Peter

We may fully decouple our business and presentation application layers when we use the Model-View-Control (MVC) pattern in our development projects. Additionally, the presentation layer will be controlled by a totally separate object. As you'll see below, the MVC's provision of object/layer independence will facilitate code reuse and improve maintenance of our project.


Generally speaking, we aim to minimize object dependencies in our projects so that we can reuse the code we've spent so much time on and make modifications easier. We will use the MVC pattern and the broader idea of "programming to the interface, not the class" to achieve this.

Our mission, if we choose to accept it.

We have been commissioned to build an ACME 2000 Sports Car business object and our task is to create a simple Windows interface to (1) display the vehicle's current direction and speed, and (2) enable the end user to change direction, accelerate, and decelerate. And of course, there will be scope creep.

There are already rumors at ACME that if our project is successful, we will eventually need to develop a similar interface for the ACME 2 Pickup Truck and the ACME 1 Tricycle. As developers, we also know that the ACME management team will eventually say "Hey, this is really cool. Can we see it on the company's intranet?" With all of this in mind, we want to deliver a product that will be easily scalable so we can be sure to have food on our plates for some time.

So, coincidentally, we think "This is a perfect situation to use the MVC!!".

Our Architecture Overview

Ok, now we know that we want to use the MVC, we need to figure out what the heck it is. Through our research, we come up with the three parts of the MVC: The Model, Control, and View. In our system, the Model would be our car, the View would be the user interface, and the Control is what ties the two together.

To make any changes to the Model (our ACME 2000 sports car), we'll be using our Control. Our Control will make the request to the Model (our ACME 2000 sports car), and update our View, which is our user interface (UI). This seems simple enough, but here's the first problem we have to solve: What happens when the end user wants to make a change to our ACME 2000 sports car, such as going faster or turning? They are going to have to do it by requesting a change using the Control, through the View (our Windows form).


Now we are left with one last problem to solve. What if the View doesn't have the necessary information to display the current state of the Model? We're going to have to add one more arrow to our diagram.  The View will be able to request the Model's state in order to get what it needs to display the information about the state of the Model.

Model's state


Finally, our end user (our driver) will be interacting with our entire ACME Vehicle Control system through the View. If they want to request a change to the system, such as adding a bit of acceleration, the request will be initiated from the View and handled by the Control.

The Control will then ask the Model to change and make any necessary changes to the View. For example, if the ACME 2000 Sports Car has a "floor it" request from an unruly driver and is now traveling to fast to make a turn, the Control will know to disable the ability to turn in the View, thus preventing a catastrophic pileup in the middle of rush-hour (whew!).

The Model (the ACME 2000 Sports Car) will notify the View that its speed has increased and the View will update where appropriate.

So after all that, here's the overview of what we will be building.


Getting Started, Parts, Parts, Parts
Being developers who always think ahead, we want to be sure our system will have a long and prosperous life. This means being prepared for as many changes at ACME as possible. In order to do this we know to follow two golden rules. "keep your classes loosely coupled" and, in order to accomplish this. "program to the interface".

So we will make three interfaces (as you may have guessed, one for the Model, one for the View, and one for the Control).

After much research and laborious interviews with the folks at ACME, we find out more about the system specifications. We want to be sure that we can set the maximum speeds for traveling forward, backward, and turning. We also need to be able to speed up, slow down, and turn left and right. Our "dashboard" view must display the current speed and direction.

It's a tall order to implement all of these requirements, but we're sure we can handle it.

First, let's take care of some preliminary items. We'll need something to represent the direction and turn requests. We'll create two enumerables, AbsoluteDirection and RelativeDirection.
public enum AbsoluteDirection
{
    North = 0,
    East,
    South,
    West
}

public enum RelativeDirection
{
    Right,
    Left,
    Back
}

Next, let's tackle the Control interface. We know the Control has to pass requests to the Model, specifically: Accelerate, Decelerate, and Turn. We'll create an IVehicleControl interface with the appropriate methods.
public interface IVehicleControl
{
    void Accelerate(int paramAmount);
    void Decelerate(int paramAmount);
    void Turn(RelativeDirection paramDirection);
}

Now we'll put together the Model interface. We need to know the Vehicle's name, speed, maximum speed, maximum reverse speed, maximum turn speed, and direction. We also need methods to accelerate, decelerate, and turn.
public interface IVehicleModel
{
    string Name { get; set; }
    int Speed { get; set; }
    int MaxSpeed { get; }
    int MaxTurnSpeed { get; }
    int MaxReverseSpeed { get; }
    AbsoluteDirection Direction { get; set; }
    void Turn(RelativeDirection paramDirection);
    void Accelerate(int paramAmount);
    void Decelerate(int paramAmount);
}

Finally, we'll put together the View interface. We know the view should expose some functionality to the Control, such as enabling and disabling acceleration, deceleration, and turn requests.
public class IVehicleView
{
    void DisableAcceleration();
    void EnableAcceleration();
    void DisableDeceleration();
    void EnableDeceleration();
    void DisableTurning();
    void EnableTurning();
}

Now we have to make a few tweaks to our interfaces to allow them to interact. First of all, any Control should be aware of it's View and Model, so we'll add "SetModel" and "SetView" methods to our IvehicleControl interface.
public interface IVehicleControl
{
    void RequestAccelerate(int paramAmount);
    void RequestDecelerate(int paramAmount);
    void RequestTurn(RelativeDirection paramDirection);
    void SetModel(IVehicleModel paramAuto);
    void SetView(IVehicleView paramView);
}

The next part is a bit tricky. We want the View to be aware of changes in the Model. To do this we'll use a GOF design pattern "Observer".

To implement the Observer pattern, we need to add the following methods to the Model (which will be "observed" by the View): AddObserver, RemoveObserver, and NotifyObservers.
public interface IVehicleModel
{
    string Name { get; set; }
    int Speed { get; set; }
    int MaxSpeed { get; }
    int MaxTurnSpeed { get; }
    int MaxReverseSpeed { get; }
    AbsoluteDirection Direction { get; set; }
    void Turn(RelativeDirection paramDirection);
    void Accelerate(int paramAmount);
    void Decelerate(int paramAmount);
    void AddObserver(IVehicleView paramView);
    void RemoveObserver(IVehicleView paramView);
    void NotifyObservers();
}


And add the following method to the View (which will be "observing" the Model). What will happen is the Model will have a reference to the View. When the Model changes, it will call the NotifyObservers() method pass a reference to itself, and notify the View of a change by calling the Update() method of the View. (It will become clear as mud when we wire everything up later).
public class IVehicleView
{
    void DisableAcceleration();
    void EnableAcceleration();
    void DisableDeceleration();
    void EnableDeceleration();
    void DisableTurning();
    void EnableTurning();
    void Update(IVehicleModel paramModel);
}


So now we have our interfaces put together. We are only going to use references to these interfaces in the rest of our code to ensure we have loose coupling (which we know is a good thing). Any user interface that shows the state of a Vehicle will implement IVehicleView, all of our ACME automobiles will implement IVehicleModel, and we'll make controls for our ACME automobiles with ACME vehicle controls which will implement IVehicleControl.

Next, What things will have things in common?

We know all our vehicles should act the same, so we're going to create a common code base "skeleton" to handle their operation. This is going to be an abstract class because we don't want anyone driving around a skeleton (you can't make an instance of an abstract class). We'll call it Automobile. We'll use an ArrayList (from System. Collections) to keep track of all the interested Views (remember the Observer pattern?). We could have used a plain old array of IVehicleView references, but we're all getting fatigued at this point and want to get through this article. If you're interested, check out the implementation of the AddObserver, RemoveObserver, and NotifyObservers methods to get an idea of how the Observer pattern works by helping our IVehicleModel interact with the IVehicleView. Every time there is a change in speed or direction, the Automobile notifies all IVehicleViews.
public abstract class Automobile : IVehicleModel
{
    #region Declarations
    private ArrayList aList = new ArrayList();
    private int mintSpeed = 0;
    private int mintMaxSpeed = 0;
    private int mintMaxTurnSpeed = 0;
    private int mintMaxReverseSpeed = 0;
    private AbsoluteDirection mDirection = AbsoluteDirection.North;
    private string mstrName = "";
    #endregion
    #region Constructor
    public Automobile(int paramMaxSpeed, int paramMaxTurnSpeed, int paramMaxReverseSpeed, string paramName)
    {
        this.mintMaxSpeed = paramMaxSpeed;
        this.mintMaxTurnSpeed = paramMaxTurnSpeed;
        this.mintMaxReverseSpeed = paramMaxReverseSpeed;
        this.mstrName = paramName;
    }
    #endregion
    #region IVehicleModel Members
    public void AddObserver(IVehicleView paramView)
    {
        aList.Add(paramView);
    }
    public void RemoveObserver(IVehicleView paramView)
    {
        aList.Remove(paramView);
    }
    public void NotifyObservers()
    {
        foreach (IVehicleView view in aList)
        {
            view.Update(this);
        }
    }
    public string Name
    {
        get
        {
            return this.mstrName;
        }
        set
        {
            this.mstrName = value;
        }
    }
    public int Speed
    {
        get
        {
            return this.mintSpeed;
        }
    }
    public int MaxSpeed
    {
        get
        {
            return this.mintMaxSpeed;
        }
    }
    public int MaxTurnSpeed
    {
        get
        {
            return this.mintMaxTurnSpeed;
        }
    }
    public int MaxReverseSpeed
    {
        get
        {
            return this.mintMaxReverseSpeed;
        }
    }
    public AbsoluteDirection Direction
    {
        get
        {
            return this.mDirection;
        }
    }
    public void Turn(RelativeDirection paramDirection)
    {
        AbsoluteDirection newDirection;
        switch (paramDirection)
        {
            case RelativeDirection.Right:
                newDirection = (AbsoluteDirection)((int)(this.mDirection + 1) % 4);
                break;
            case RelativeDirection.Left:
                newDirection = (AbsoluteDirection)((int)(this.mDirection + 3) % 4);
                break;
            case RelativeDirection.Back:
                newDirection = (AbsoluteDirection)((int)(this.mDirection + 2) % 4);
                break;
            default:
                newDirection = AbsoluteDirection.North;
                break;
        }
        this.mDirection = newDirection;
        this.NotifyObservers();
    }
    public void Accelerate(int paramAmount)
    {
        this.mintSpeed += paramAmount;
        if (mintSpeed >= this.mintMaxSpeed) mintSpeed = mintMaxSpeed;
        this.NotifyObservers();
    }
    public void Decelerate(int paramAmount)
    {
        this.mintSpeed -= paramAmount;
        if (mintSpeed <= this.mintMaxReverseSpeed) mintSpeed = mintMaxReverseSpeed;
        this.NotifyObservers();
    }
    #endregion
}


Last but not least
Now that our "ACME Framework" is in place, we just have to set up our concrete classes and our interface. Let's take care of the last two classes first which will be our Control and our Model.

Here's our concrete AutomobileControl which implements the IVehicleControl interface. Our AutomobileControl will also set the View depending on the state of the Model (check out the SetView method which is called every time there is a request passed to the Model).

Notice, we just have references to the IVehicleModel (not the Automobile abstract class) to keep things loose and IVehicleView (not a specific View).
public class AutomobileControl : IVehicleControl
{
    private IVehicleModel Model;
    private IVehicleView View;
    public AutomobileControl(IVehicleModel paramModel, IVehicleView paramView)
    {
        this.Model = paramModel;
        this.View = paramView;
    }
    public AutomobileControl()
    {
    }
    #region IVehicleControl Members
    public void SetModel(IVehicleModel paramModel)
    {
        this.Model = paramModel;
    }
    public void SetView(IVehicleView paramView)
    {
        this.View = paramView;
    }
    public void RequestAccelerate(int paramAmount)
    {
        if (Model != null)
        {
            Model.Accelerate(paramAmount);
            if (View != null) SetView();
        }
    }
    public void RequestDecelerate(int paramAmount)
    {
        if (Model != null)
        {
            Model.Decelerate(paramAmount);
            if (View != null) SetView();
        }
    }
    public void RequestTurn(RelativeDirection paramDirection)
    {
        if (Model != null)
        {
            Model.Turn(paramDirection);
            if (View != null) SetView();
        }
    }
    #endregion
    public void SetView()
    {
        if (Model.Speed >= Model.MaxSpeed)
        {
            View.DisableAcceleration();
            View.EnableDeceleration();
        }
        else if (Model.Speed <= Model.MaxReverseSpeed)
        {
            View.DisableDeceleration();
            View.EnableAcceleration();
        }
        else
        {
            View.EnableAcceleration();
            View.EnableDeceleration();
        }
        if (Model.Speed >= Model.MaxTurnSpeed)
        {
            View.DisableTurning();
        }
        else
        {
            View.EnableTurning();
        }
    }
}

Here's our ACME200SportsCar class (which extends the Automobile abstract class which implements the IVehicleModel interface).
public class ACME2000SportsCar : Automobile
{
    public ACME2000SportsCar(string paramName) : base(250, 40, -20, paramName) { }
    public ACME2000SportsCar(string paramName, int paramMaxSpeed, int paramMaxTurnSpeed, int paramMaxReverseSpeed) :
        base(paramMaxSpeed, paramMaxTurnSpeed, paramMaxReverseSpeed, paramName)
    { }
}

And now for our View.
Now we have to create the last of our three ACME MVC components the View.
We'll create an AutoView user control and have it implement the IVehicleView interface. The AutoView component will have references to our control and model interfaces.
public class AutoView : System.Windows.Forms.UserControl, IVehicleView
{
    private IVehicleControl Control = new ACME.AutomobileControl();
    private IVehicleModel Model = new ACME.ACME2000SportsCar("Speedy");
}


We also need to wire everything up in the constructor for the UserControl.
public AutoView()
{
    // This call is required by the Windows.Forms Form Designer.
    InitializeComponent();
    WireUp(Control, Model);
}
public void WireUp(IVehicleControl paramControl, IVehicleModel paramModel)
{
    // If we're switching Models, don't keep watching the old one!
    if (Model != null)
    {
        Model.RemoveObserver(this);
    }
    Model = paramModel;
    Control = paramControl;
    Control.SetModel(Model);
    Control.SetView(this);
    Model.AddObserver(this);
}

Next, we'll add our buttons, a label to display the status of the ACME2000 Sports Car, and a status bar just for kicks and fill out the code for all the buttons.

private void btnAccelerate_Click(object sender, System.EventArgs e)
{
    Control.RequestAccelerate(int.Parse(this.txtAmount.Text));
}
private void btnDecelerate_Click(object sender, System.EventArgs e)
{
    Control.RequestDecelerate(int.Parse(this.txtAmount.Text));
}
private void btnLeft_Click(object sender, System.EventArgs e)
{
    Control.RequestTurn(RelativeDirection.Left);
}
private void btnRight_Click(object sender, System.EventArgs e)
{
    Control.RequestTurn(RelativeDirection.Right);
}

Add a method to update the interface
public void UpdateInterface(IVehicleModel auto)
{
    this.label1.Text = auto.Name + " heading " + auto.Direction.ToString() + " at speed: " + auto.Speed.ToString();
    this.pBar.Value = (auto.Speed > 0) ? auto.Speed * 100 / auto.MaxSpeed : auto.Speed * 100 / auto.MaxReverseSpeed;
}

Finally, we'll wire up the IVehicleView interface methods.
public void DisableAcceleration()
{
    this.btnAccelerate.Enabled = false;
}
public void EnableAcceleration()
{
    this.btnAccelerate.Enabled = true;
}
public void DisableDeceleration()
{
    this.btnDecelerate.Enabled = false;
}
public void EnableDeceleration()
{
    this.btnDecelerate.Enabled = true;
}
public void DisableTurning()
{
    this.btnRight.Enabled = this.btnLeft.Enabled = false;
}
public void EnableTurning()
{
    this.btnRight.Enabled = this.btnLeft.Enabled = true;
}
public void Update(IVehicleModel paramModel)
{
    this.UpdateInterface(paramModel);
}


And we're off. Now we can go for a test drive in the ACME2000 Sports Car. Everything is going as planned and then we run into an ACME executive who wants to drive a pickup truck instead of a sports car. Good thing we used the MVC! All we need to do is create a new ACMETruck class, wire it up, and we're in business.
public class ACME2000Truck : Automobile
{
    public ACME2000Truck(string paramName) : base(80, 25, -12, paramName) { }

    public ACME2000Truck(string paramName, int paramMaxSpeed, int paramMaxTurnSpeed, int paramMaxReverseSpeed) :
        base(paramMaxSpeed, paramMaxTurnSpeed, paramMaxReverseSpeed, paramName)
    { }
}


in the AutoView, we just have to build the truck and wire it up.
private void btnBuildNew_Click(object sender, System.EventArgs e)
{
    this.autoView1.WireUp(new ACME.AutomobileControl(), new ACME.ACME2000Truck(this.txtName.Text));
}


If we wanted a new Control that only allowed us to increase or decrease the speed by a maximum of 5mph, it's a snap! Create a SlowPokeControl (same as our AutoControl, but with limits on how much a Model will be requested to accelerate).
public void RequestAccelerate(int paramAmount)
{
    if (Model != null)
    {
        int amount = paramAmount;
        if (amount > 5) amount = 5;
        Model.Accelerate(amount);
        if (View != null) SetView();
    }
}
public void RequestDecelerate(int paramAmount)
{
    if (Model != null)
    {
        int amount = paramAmount;
        if (amount > 5) amount = 5;
        Model.Accelerate(amount);  // Typo fixed: should be Decelerate instead of Accelerate
        Model.Decelerate(amount);
        if (View != null) SetView();
    }
}


If we want to make our ACME2000 Truck a SlowPoke, we just wire it up in the AutoView.
private void btnBuildNew_Click(object sender, System.EventArgs e)
{
    this.autoView1.WireUp(new ACME.SlowPokeControl(), new ACME.ACME2000Truck(this.txtName.Text));
}


Finally, if we wanted a web-enabled interface, all we have to do is create a web project and on the UserControl implement the IVehicleView interface.

Conclusion

As you can see, using the MVC to help build code to control interfaces that are very loosely coupled makes life much easier when it comes to change requests. It also makes the impact of changes negligible and you can reuse your interfaces and abstract classes almost anywhere. There are a couple of places where we can build some more flexibility in our project, especially in terms of requesting changes to our Model's state, but that will have to wait for next time.



ASP.NET MVC Hosting - HostForLIFEASP.NET :: Repository Pattern With ASP.NET MVC And Entity Framework

clock October 18, 2024 08:20 by author Peter

An application's data access layer and business logic layer are separated by an abstraction layer that is created using the repository pattern. The business logic layer (BAL) receives data from the repository via direct communication with the data access layer (DAL). The primary benefit of employing a repository pattern is its ability to separate the business and data access logic, preventing modifications to one from having an immediate impact on the other.


I'll go over how to leverage repository patterns in EntityFramework-powered ASP.NET MVC today.

Step 1

  • Start Visual Studio 2013 or 2012.
  • Create a new project -> Web -> Visual Studio 2012.
  • Select ASP.NET MVC 4 Web Application.
  • Provide the Name and Location for the project and click Next.
  • Choose Basic template as the project template and click OK.


Step 2. Create an EmployeeContext.cs and Employee.cs entity class inside the Model folder for the database factory. You can create a database and table manually or if you use my approach it will create a database and table automatically when you run the application the first time because I have used here code first approach.

Employee.cs

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Web;

namespace RepositoryWithMVC.Models
{
    [Table("Employee")]
    public class Employee
    {
        [Key]
        public int EmployeeId
        {
            get;
            set;
        }

        [Display(Name = "Employee Name")]
        [Required(ErrorMessage = "Name is required")]
        public string EmployeeName
        {
            get;
            set;
        }

        [Display(Name = "Address")]
        [Required(ErrorMessage = "Address is required")]
        public string Address
        {
            get;
            set;
        }

        [Required(ErrorMessage = "Email Id is required")]
        public string EmailId
        {
            get;
            set;
        }
    }
}

EmployeeContext.cs
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;

namespace RepositoryWithMVC.Models
{
    public class EmployeeContext : DbContext
    {
        public EmployeeContext() : base("DefaultConnection") {}

        public DbSet<Employee> Employees
        {
            get;
            set;
        }
    }
}

Web.Config
<connectionStrings>
    <add name="DefaultConnection"
         connectionString="data source=(local); database=Demodb; user id=sa; password=xyz;"
         providerName="System.Data.SqlClient" />
</connectionStrings>


Step 3. Create a folder with the name “Repository” inside your project. Add an interface and a class respectively IEmployeeRepository.cs and EmployeeRepository.cs.
IEmployeeRepository.cs
using RepositoryWithMVC.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace RepositoryWithMVC.Repository
{
    public interface IEmployeeRepository : IDisposable
    {
        IEnumerable<Employee> GetAllEmployee();
        Employee GetEmployeeById(int studentId);
        int AddEmployee(Employee employeeEntity);
        int UpdateEmployee(Employee employeeEntity);
        void DeleteEmployee(int employeeId);
    }
}

EmployeeRepository.cs
using RepositoryWithMVC.Models;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;

namespace RepositoryWithMVC.Repository
{
    public class EmployeeRepository : IEmployeeRepository
    {
        private readonly EmployeeContext _context;

        public EmployeeRepository(EmployeeContext context)
        {
            _context = context;
        }

        public IEnumerable<Employee> GetAllEmployee()
        {
            return _context.Employees.ToList();
        }

        public Employee GetEmployeeById(int studentId)
        {
            return _context.Employees.Find(studentId);
        }

        public int AddEmployee(Employee employeeEntity)
        {
            int result = -1;

            if (employeeEntity != null)
            {
                _context.Employees.Add(employeeEntity);
                _context.SaveChanges();
                result = employeeEntity.EmployeeId;
            }

            return result;
        }

        public int UpdateEmployee(Employee employeeEntity)
        {
            int result = -1;

            if (employeeEntity != null)
            {
                _context.Entry(employeeEntity).State = EntityState.Modified;
                _context.SaveChanges();
                result = employeeEntity.EmployeeId;
            }

            return result;
        }

        public void DeleteEmployee(int employeeId)
        {
            Employee employeeEntity = _context.Employees.Find(employeeId);
            _context.Employees.Remove(employeeEntity);
            _context.SaveChanges();
        }

        private bool disposed = false;

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    _context.Dispose();
                }
            }
            this.disposed = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }
}


Step 4. Add an EmployeeController that directly interacts with the Repository.
using RepositoryWithMVC.Models;
using RepositoryWithMVC.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace RepositoryWithMVC.Controllers
{
    public class EmployeeController : Controller
    {
        private IEmployeeRepository _employeeRepository;

        public EmployeeController()
        {
            _employeeRepository = new EmployeeRepository(new Models.EmployeeContext());
        }

        public EmployeeController(IEmployeeRepository employeeRepository)
        {
            _employeeRepository = employeeRepository;
        }

        public ActionResult Index()
        {
            var model = _employeeRepository.GetAllEmployee();
            return View(model);
        }

        public ActionResult AddEmployee()
        {
            if (TempData["Failed"] != null)
            {
                ViewBag.Failed = "Add Employee Failed";
            }
            return View();
        }

        [HttpPost]
        public ActionResult AddEmployee(Employee model)
        {
            if (ModelState.IsValid)
            {
                int result = _employeeRepository.AddEmployee(model);
                if (result > 0)
                {
                    return RedirectToAction("Index", "Employee");
                }
                else
                {
                    TempData["Failed"] = "Failed";
                    return RedirectToAction("AddEmployee", "Employee");
                }
            }
            return View();
        }

        public ActionResult EditEmployee(int employeeId)
        {
            if (TempData["Failed"] != null)
            {
                ViewBag.Failed = "Edit Employee Failed";
            }
            Employee model = _employeeRepository.GetEmployeeById(employeeId);
            return View(model);
        }

        [HttpPost]
        public ActionResult EditEmployee(Employee model)
        {
            if (ModelState.IsValid)
            {
                int result = _employeeRepository.UpdateEmployee(model);
                if (result > 0)
                {
                    return RedirectToAction("Index", "Employee");
                }
                else
                {
                    return RedirectToAction("Index", "Employee");
                }
            }
            return View();
        }

        public ActionResult DeleteEmployee(int employeeId)
        {
            Employee model = _employeeRepository.GetEmployeeById(employeeId);
            return View(model);
        }

        [HttpPost]
        public ActionResult DeleteEmployee(Employee model)
        {
            if (TempData["Failed"] != null)
            {
                ViewBag.Failed = "Delete Employee Failed";
            }
            _employeeRepository.DeleteEmployee(model.EmployeeId);
            return RedirectToAction("Index", "Employee");
        }
    }
}


Step 5. Create a View for the Controller action method like Index, EditEmployee, DeleteEmployee, etc.
Index.cshtml
@model IEnumerable<RepositoryWithMVC.Models.Employee>

@{
    ViewBag.Title = "Index";
}

<div align="center">
    <h3>Employee Management</h3>
    <span>
        <a href="@Url.Action("AddEmployee", "Employee")">Add Employee</a>
    </span>
    <br />
    <br />
    <table cellpadding="5" border="1">
        <tr style="background-color:#808080; color:white;">
            <td>Employee Id</td>
            <td>Name</td>
            <td>Address</td>
            <td>Email Id</td>
            <td>Action</td>
        </tr>
        @foreach (var emp in Model)
        {
            <tr>
                <td>@emp.EmployeeId</td>
                <td>@emp.EmployeeName</td>
                <td>@emp.Address</td>
                <td>@emp.EmailId</td>
                <td>
                    <a href="@Url.Action("EditEmployee", "Employee", new { EmployeeId = emp.EmployeeId })">Edit</a>
                    <a href="@Url.Action("DeleteEmployee", "Employee", new { EmployeeId = emp.EmployeeId })">Delete</a>
                </td>
            </tr>
        }
    </table>
</div>


AddEmployee.cshtml
@model RepositoryWithMVC.Models.Employee

@{
    ViewBag.Title = "AddEmployee";
}

<div align="center">
    <h3>Employee Management</h3>
    <br />
    <b>Add New Employee</b>
    <br />
    <br />

    @using (Html.BeginForm("AddEmployee", "Employee", FormMethod.Post))
    {
        <table>
            <tr>
                <td colspan="2">
                    @if (ViewBag.Failed != null)
                    {
                        <span style="color:red;">@ViewBag.Failed</span>
                    }
                </td>
            </tr>
            <tr>
                <td>
                    @Html.LabelFor(e => e.EmployeeName)
                </td>
                <td>
                    @Html.TextBoxFor(e => e.EmployeeName)
                    <br />
                    @Html.ValidationMessageFor(e => e.EmployeeName, null, new { style = "color:red;" })
                </td>
            </tr>
            <tr>
                <td>
                    @Html.LabelFor(e => e.Address)
                </td>
                <td>
                    @Html.TextBoxFor(e => e.Address)
                    <br />
                    @Html.ValidationMessageFor(e => e.Address, null, new { style = "color:red;" })
                </td>
            </tr>
            <tr>
                <td>
                    @Html.LabelFor(e => e.EmailId)
                </td>
                <td>
                    @Html.TextBoxFor(e => e.EmailId)
                    <br />
                    @Html.ValidationMessageFor(e => e.EmailId, null, new { style = "color:red;" })
                </td>
            </tr>
            <tr>
                <td colspan="2" align="center">
                    <br />
                    <input type="submit" value="Submit" />
                </td>
            </tr>
        </table>
    }
</div>


EditEmployee.cshtml
@model RepositoryWithMVC.Models.Employee

@{
    ViewBag.Title = "Edit Employee";
}

<div align="center">
    <h3>Employee Management</h3>
    <br />
    <b>Edit Employee</b>
    <br />
    <br />

    @using (Html.BeginForm("EditEmployee", "Employee", FormMethod.Post))
    {
        @Html.HiddenFor(e => e.EmployeeId)
        <table>
            <tr>
                <td colspan="2">
                    @if (ViewBag.Failed != null)
                    {
                        <span style="color:red;">@ViewBag.Failed</span>
                    }
                </td>
            </tr>
            <tr>
                <td>
                    @Html.LabelFor(e => e.EmployeeName)
                </td>
                <td>
                    @Html.TextBoxFor(e => e.EmployeeName)
                    <br />
                    @Html.ValidationMessageFor(e => e.EmployeeName, null, new { style = "color:red;" })
                </td>
            </tr>
            <tr>
                <td>
                    @Html.LabelFor(e => e.Address)
                </td>
                <td>
                    @Html.TextBoxFor(e => e.Address)
                    <br />
                    @Html.ValidationMessageFor(e => e.Address, null, new { style = "color:red;" })
                </td>
            </tr>
            <tr>
                <td>
                    @Html.LabelFor(e => e.EmailId)
                </td>
                <td>
                    @Html.TextBoxFor(e => e.EmailId)
                    <br />
                    @Html.ValidationMessageFor(e => e.EmailId, null, new { style = "color:red;" })
                </td>
            </tr>
            <tr>
                <td colspan="2" align="center">
                    <br />
                    <input type="submit" value="Update" />
                </td>
            </tr>
        </table>
    }
</div>


DeleteEmployee.cshtml
@model RepositoryWithMVC.Models.Employee

@{
    ViewBag.Title = "Delete Employee";
}

<div align="center">
    <h3>Employee Management</h3>
    <br />

    @using (Html.BeginForm("DeleteEmployee", "Employee", FormMethod.Post))
    {
        @Html.HiddenFor(e => e.EmployeeId)
        <table border="1" cellpadding="10">
            <tr>
                <td colspan="2" align="center">
                    <b>Delete Employee</b>
                    @if (ViewBag.Failed != null)
                    {
                        <span style="color:red;">@ViewBag.Failed</span>
                    }
                </td>
            </tr>
            <tr>
                <td>
                    @Html.LabelFor(e => e.EmployeeName)
                </td>
                <td>
                    @Html.TextBoxFor(e => e.EmployeeName, new { @readonly = "readonly" })
                </td>
            </tr>
            <tr>
                <td>
                    @Html.LabelFor(e => e.Address)
                </td>
                <td>
                    @Html.TextBoxFor(e => e.Address, new { @readonly = "readonly" })
                </td>
            </tr>
            <tr>
                <td>
                    @Html.LabelFor(e => e.EmailId)
                </td>
                <td>
                    @Html.TextBoxFor(e => e.EmailId, new { @readonly = "readonly" })
                </td>
            </tr>
            <tr>
                <td colspan="2" align="center">
                    <br />
                    <input type="submit" value="Delete" />
                </td>
            </tr>
        </table>
    }
</div>


Note. Change in RouteConfig.cs controller name from home to employee in default.

Thanks for reading this article, hope you enjoyed it.



About HostForLIFE.eu

HostForLIFE.eu 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 2016 Hosting, ASP.NET Core 2.2.1 Hosting, ASP.NET MVC 6 Hosting and SQL 2017 Hosting.


Tag cloud

Sign in