locked
Problems Passing Model from Entity Framework RRS feed

  • Question

  • User1122355199 posted

    Hello everyone and thanks for the help in advance.  I'm trying to learn Entity Framework code first.  I have a model that looks like this:

        public class Patient
        {
            [Key]
            public int ID { get; set; }
            public string PatientLastName { get; set; }
            public string PatientFirstName { get; set; }
        }

    The controller looks like:

            public ActionResult Index()
            {
                var ctx = new PatientContext();
                //var patient = ctx.Patients.Find(1);
                string name = "Smith";
                var patients = ctx.Patients
                              .Where(s => s.PatientLastName == name).ToList();
                
                ViewBag.TotalPatients = patients.Count.ToString();
    
                return View(patients);
            }

    The  View looks like:

    @model Patient
    @{
        Layout = null;
    }
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title></title>
    </head>
    <body>
        <div>
            @ViewBag.TotalPatients
        </div>
        <table>
            <tr>
                <th>
                    @Html.DisplayNameFor(model => model.PatientLastName)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.PatientFirstName)
                </th>
                <th></th>
            </tr>
    
            @foreach (var item in Model.PatientFirstName)
            {
                <tr>
                    <td>
                        @Html.DisplayFor(modelItem => item.PatientLastName)
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.PatientFirstMidName)
                    </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>
    </body>
    </html>
    

    I'm receiving the error:   'char' does not contain a definition for 'PatientLastName' and no extension method 'PatientLastName' accepting a first argument of type 'char' could be found (are you missing a using directive or an assembly reference?).  I'm not sure how to fix this error.  Any help would be appreciated.

    Saturday, July 13, 2019 5:10 PM

Answers

  • User1120430333 posted

    Thanks for the response. I appreciate the learning experience and am really trying to take in all of the lessons. I'm struggling is a few spots including interfaces, why use them, when to use them, etc. I am able to access the DaoPatient GetAll() but can't seem to access IDaoPatient. I haven't figure out how to return either of these successfully to the controller and the view.

    And about the above, you can access IDaoPatient by doing something like this.

    var data =  SomeClass( new IDaoPatient).GetSomeData().ToLIat()

    The SomeClass exxpects the DoaPatient class/object to be DI into SomeClass' constructor so that it can be used by GetSomeData(). Of course a new IDaoPatierent is instancing DaoPatient.

    The above can be done during a unit test to satisfy the requirement of SomeClass that expects DaoPatient is going to be injected into SomeClass.

    . You see the constructor for AuthorController(IAuthorDM  authorDM) is specifying that AuthorDM be injected into it and that' s how you do it  by the class's Interface in the constrctor. The AuthorDM was instanced by the Core IoC,  and it was DI into the class by the Core IoC . You see the Core IoC being configured to use the classes and their Interfaces.

    Below that, a VB.NET MVC5 example using the Unity IoC  that is registering the classes along with their Interfaces so that they can be DI into the solution when needed. One set is for the ASP.NET Identity classes and their interfaces as well that are controlled by the IoC

    In the Windows forms MVC solution, by the way MVC started out on desktop solutions well before it got to the Web, you can see the Interface being used, 

    https://www.codeproject.com/Articles/383153/The-Model-View-Controller-MVC-Pattern-with-Csharp

    using Microsoft.AspNetCore.Mvc;
    using PublishingCompany.Models;
    
    namespace PublishingCompany.Controllers
    {
        public class AuthorController : Controller
        {
            private IAuthorDM adm;
            public AuthorController(IAuthorDM authorDM)
            {
                adm = authorDM;
            }
    
            public IActionResult Index()
            {
                return View(adm.GetAll());
            }
    
            public IActionResult Detail(int id = 0)
            {
                return id == 0 ? null : View(adm.Find(id));
            }
    
            public IActionResult Create()
            {
                return View(adm.Add());
            }
    
            [HttpPost]
            public ActionResult Create(AuthorVM.Author author, string submit)
            {
                if (submit == "Cancel") return RedirectToAction("Index");
    
                if (!ModelState.IsValid) return View(author);
    
                adm.Add(author);
                return RedirectToAction("Index");
            }
            
            public ActionResult Edit(int id = 0)
            {
                return id == 0 ? null : View(adm.Update(id));
            }
            
            [HttpPost]
            public ActionResult Edit(AuthorVM.Author author, string submit)
            {
                if (submit == "Cancel") return RedirectToAction("Index");
                            
                if (!ModelState.IsValid) return View(author);
                           
                adm.Update(author);
                return RedirectToAction("Index");
            }
            public IActionResult Delete(int id = 0)
            {
                if (id > 0) adm.Delete(id);
    
                return RedirectToAction("Index");
            }
    
            public ActionResult Cancel()
            {
                return RedirectToAction("Index", "Home");
            }
        }
    }
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Logging;
    using Serilog;
    using ServiceLayer;
    using PublishingCompany.Models;
    
    namespace PublishingCompany
    {
        public class Startup
        {
            public Startup(IConfiguration configuration)
            {
                Configuration = configuration;
                Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(configuration).CreateLogger();
            }
    
            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.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    
                //Domain Model
                services.AddTransient<IAuthorDM, AuthorDM>();
                services.AddTransient<IPayRollDM, PayRollDM>();
                services.AddTransient<IArticleDM, ArticleDM>();
    
                //ServiceLayer
                services.AddTransient<IAuthorSvc, AuthorSvc>();
                services.AddTransient<IPayRollSvc, PayRollSvc>();
                services.AddTransient<IArticleSvc, ArticleSvc>();
            }
    
            // 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)
            {
                loggerFactory.AddSerilog();
    
                app.UseExceptionHandler("/Home/Error");
                
                app.UseStaticFiles();
                app.UseCookiePolicy();
    
                app.UseMvc(routes =>
                {
                    routes.MapRoute(
                        name: "default",
                        template: "{controller=Home}/{action=Index}/{id?}");
                });
            }
        }
    }
    
    Imports System.Data.Entity
    Imports Microsoft.AspNet.Identity
    Imports Microsoft.AspNet.Identity.EntityFramework
    Imports ProgMgmntVB.Controllers
    Imports ProgMgmntVB.Models
    Imports ProgMgmntVB.WebApi
    Imports Unity
    Imports Unity.Injection
    Imports Unity.Lifetime
    Imports Unity.Mvc5
    
    Module ModuleUnity
    
        public class UnityConfig
    
            public shared sub RegisterComponents()
    
                dim container = new UnityContainer()
    
                container.RegisterType(Of IProjectModel, ProjectModel)() 
                container.RegisterType(Of ITaskModel, TaskModel)()
                container.RegisterType(Of IWebApi, WebApi.WebApi)()
                container.RegisterType(Of IModelHelper, ModelHelper)()
    
                'Idenity 
    
                container.RegisterType(Of DbContext, ApplicationDbContext)(new HierarchicalLifetimeManager())
                container.RegisterType(of UserManager(of ApplicationUser))(new HierarchicalLifetimeManager())
                container.RegisterType(of IUserStore(of ApplicationUser), UserStore(of ApplicationUser))(New HierarchicalLifetimeManager())
                container.RegisterType(of AccountController)(new InjectionConstructor())
    
                DependencyResolver.SetResolver(new UnityDependencyResolver(container))
    
            End sub
        
        End Class
    End Module
    

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Saturday, August 3, 2019 8:16 AM
  • User475983607 posted

    That clarifies some of my confusions.  But why use this instead of simply implementing a class?

    Interfaces are another tool in your toolbox.  The construct is very common and a subject that I recommend taking the time to learn.

    Below is a very common pattern where the a business logic class can accept any type that implements IBehavior.

        public class BusinessLogic
        {
            private readonly IBehavior _behavior;
            public BusinessLogic(IBehavior behavior)
            {
                _behavior = behavior;
            }
    
            public string Talk()
            {
                return _behavior.Talk();
            }
        }

    Implementation.

            static void Main(string[] args)
            {
                BusinessLogic bl1 = new BusinessLogic(new Person());
                BusinessLogic bl2 = new BusinessLogic(new Dog());
    
                Console.WriteLine(bl1.Talk());
                Console.WriteLine(bl2.Talk());
            }

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Saturday, August 3, 2019 12:52 PM

All replies

  • User1120430333 posted

    You should check the table column in the database to see if it's defined correctly..

    A couple of other things, like it's not optimal to have data access directly in the controller.

    https://www.c-sharpcorner.com/UploadFile/56fb14/understanding-separation-of-concern-and-Asp-Net-mvc/

    You should learn to use a viewmodel that would eliminate the usage of the viewbag, because you can't place it on the EF persistence model, but you can put it on the VM.  The VM might clear-up the char thing too.

    https://www.tutlane.com/tutorial/aspnet-mvc/how-to-use-viewmodel-in-asp-net-mvc-with-example

    https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions-1/overview/understanding-models-views-and-controllers-cs

    <copied>

    An MVC model contains all of your application logic that is not contained in a view or a controller. The model should contain all of your application business logic, validation logic, and database access logic. For example, if you are using the Microsoft Entity Framework to access your database, then you would create your Entity Framework classes (your .edmx file) in the Models folder.

    A view should contain only logic related to generating the user interface. A controller should only contain the bare minimum of logic required to return the right view or redirect the user to another action (flow control). Everything else should be contained in the model.

    In general, you should strive for fat models and skinny controllers. Your controller methods should contain only a few lines of code. If a controller action gets too fat, then you should consider moving the logic out to a new class in the Models folder.

    <end>

    An example where the controller is calling a class in the Models folder and the method in the class is making the database call to populate the VM and return the VM to the view. The 'DM' means Domain Model, a domain model object.

    https://en.wikipedia.org/wiki/Business_logic

    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    
    namespace PublishingCompany.Models
    {
        public class AuthorVM
        {
            public class Author
            {
                public int AuthorID { get; set; }
    
                [Required(ErrorMessage = "First Name is required")]
                [StringLength(50)]
                public string FirstName { get; set; }
    
                [Required(ErrorMessage = "Last Name is required")]
                [StringLength(50)]
                public string LastName { get; set; }
            }
    
            public List<Author> Authors { get; set; } = new List<Author>();
        }
    }
    
    using Microsoft.AspNetCore.Mvc;
    using PublishingCompany.Models;
    
    namespace PublishingCompany.Controllers
    {
        public class AuthorController : Controller
        {
            private IAuthorDM adm;
            public AuthorController(IAuthorDM authorDM)
            {
                adm = authorDM;
            }
    
            public IActionResult Index()
            {
                return View(adm.GetAll());
            }
    
            public IActionResult Detail(int id = 0)
            {
                return id == 0 ? null : View(adm.Find(id));
            }
    
            public IActionResult Create()
            {
                return View(adm.Add());
            }
    
            [HttpPost]
            public ActionResult Create(AuthorVM.Author author, string submit)
            {
                if (submit == "Cancel") return RedirectToAction("Index");
    
                if (!ModelState.IsValid) return View(author);
    
                adm.Add(author);
                return RedirectToAction("Index");
            }
            
            public ActionResult Edit(int id = 0)
            {
                return id == 0 ? null : View(adm.Update(id));
            }
            
            [HttpPost]
            public ActionResult Edit(AuthorVM.Author author, string submit)
            {
                if (submit == "Cancel") return RedirectToAction("Index");
                            
                if (!ModelState.IsValid) return View(author);
                           
                adm.Update(author);
                return RedirectToAction("Index");
            }
            public IActionResult Delete(int id = 0)
            {
                if (id > 0) adm.Delete(id);
    
                return RedirectToAction("Index");
            }
    
            public ActionResult Cancel()
            {
                return RedirectToAction("Index", "Home");
            }
        }
    }
    using System.Linq;
    using ServiceLayer;
    using Entities;
    
    namespace PublishingCompany.Models
    {
        public class AuthorDM :IAuthorDM
        {
            private IAuthorSvc svc;
            public AuthorDM(IAuthorSvc authorSvc)
            {
                svc = authorSvc;
            }
    
            public AuthorVM GetAll()
            {
                var vm = new AuthorVM();
    
                var dtos = svc.GetAll().ToList();
    
                vm.Authors.AddRange(dtos.Select(dto => new AuthorVM.Author()
                {
                    AuthorID = dto.AuthorId,
                    FirstName = dto.FirstName,
                    LastName = dto.LastName
                }).ToList());
    
                return vm;
            }
    
            public AuthorVM.Author Find(int id)
            {
                var dto = svc.Find(id);
    
                var author = new AuthorVM.Author
                {
                    AuthorID = dto.AuthorId,
                    FirstName = dto.FirstName,
                    LastName = dto.LastName
                };
    
                return author;
            }
    
            public AuthorVM.Author Add()
            {
                return new AuthorVM.Author();
            }
    
            public void Add(AuthorVM.Author author)
            {
                var dto = new DtoAuthor
                {
                    FirstName = author.FirstName,
                    LastName = author.LastName
                };
    
                svc.Add(dto);
            }
    
            public AuthorVM.Author Update(int id)
            {
                var dto = Find(id);
    
                var author = new AuthorVM.Author
                {
                    AuthorID = dto.AuthorID,
                    FirstName = dto.FirstName,
                    LastName = dto.LastName
                };
    
                return author;
            }
    
            public void Update(AuthorVM.Author author)
            {
                var dto = new DtoAuthor
                {
                    AuthorId = author.AuthorID,
                    FirstName = author.FirstName,
                    LastName = author.LastName
                };
    
                svc.Update(dto);
            }
    
            public void Delete(int id)
            {
                var dto = new DtoId
                {
                    Id = id
                };
    
                svc.Delete(dto);
            }
           
        }
    }
    
    @model AuthorVM
    @{
        ViewData["Title"] = "Author Page";
    }
    
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Authors</title>
    </head>
    <body>
        <h1>Authors</h1>
    
        <form method="post">
    
            @Html.ActionLink("Create", "Create")
            @Html.ActionLink("Cancel", "Cancel")
    
            <br /><br />
            <table border="1" cellpadding="10">
                <tr>
                    <th>AuthorID</th>
                    <th>First Name</th>
                    <th>Last Name</th>
                    <th colspan="4">Actions</th>
                </tr>
                @foreach (var item in Model.Authors)
                {
                    <tr>
                        <td>@item.AuthorID</td>
                        <td>@item.FirstName</td>
                        <td>@item.LastName</td>
                        <td>
                            @Html.ActionLink("Edit", "Edit", new { id = item.AuthorID })
                        </td>
                        <td>
                            @Html.ActionLink("Detail", "Detail", new { id = item.AuthorID })
                        </td>
    
                        <td>
                            @Html.ActionLink("Delete", "Delete", new { id = item.AuthorID },
                                          new { onclick = "return confirm('Are you sure you wish to delete this author?');" })
                        </td>
    
                    </tr>
                }
            </table>
        </form>
    </body>
    </html>
    

    Saturday, July 13, 2019 6:06 PM
  • User1122355199 posted

    Thanks for the response.  I verified the table column is defined correctly but am still receiving the error.  Also, I somewhat understand your explanation regarding separation of concerns, however, the example doesn't compile.  Back to my application, the table looks like:

    CREATE TABLE [dbo].[Patients](
    	[ID] [int] IDENTITY(1,1) NOT NULL,
    	[PatientLastName] [varchar](50) NULL,
    	[PatientFirstName] [varchar](50) NULL
    ) ON [PRIMARY]
    

    I have now created a viewmodel that looks like:

        public class PatientVM
        {
            public class Patient
            {
                [Key]
                public int ID { get; set; }
    
                [Required(ErrorMessage = "Patient Last Name is required")]
                [StringLength(50)]
                public string PatientLastName { get; set; }
    
                [Required(ErrorMessage = "Patient First Name is required")]
                [StringLength(50)]
                public string PatientFirstName { get; set; }
                
            }
            public List<Patients> PatientList { get; set; } = new List<Patients>();
        }

    I'm confused how to set up the data access layer.

    Monday, July 15, 2019 1:28 AM
  • User1120430333 posted

    The Data Access Layer (DAL) is a classlib project in the solution. The DAO pattern is being used along with the DTO pattern is being used in the MVC and DAL projects. The DTO is in a classlib project called Entities,  and the MVC and DAL projects should have project reference to Entities and know what the DTO is about. The DTO travels through the layers

    https://www.tutorialspoint.com/design_pattern/data_access_object_pattern

    https://www.codeproject.com/articles/1050468/data-transfer-object-design-pattern-in-csharp

    If using EF 6, then the EF components must be installed in the MVC and DAL projects that's how it works. The EF model is used in the DAL, things are mapped between an EF model object and the DTO and vice versa for CRUD operations with the EF entity left at the DAL. The DTO is sent to the MVC or Presentation Layer in a layered style.

    https://docs.microsoft.com/en-us/previous-versions/msp-n-p/ee658117(v=pandp.10)

    using Entities;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    
    namespace DAL
    {
        public interface IDaoPayroll
        {
            Task<List<DtoPayroll>> GetAll();
            Task<DtoPayroll> Find(int id);
            Task<DtoPayroll> FindPayRollByAuthorId(int id);
            Task Add(DtoPayroll dto);
            Task Update(DtoPayroll dto);
            Task Delete(int id);
        }
    }
    
    =================================================================
    
    using DAL.Models;
    using System;
    using System.Threading.Tasks;
    using Entities;
    using System.Collections.Generic;
    using Microsoft.EntityFrameworkCore;
    using System.Data.SqlClient;
    using System.Linq;
    
    namespace DAL
    {
        public class DaoPayroll :IDaoPayroll
        {
            private PublishingCompanyContext pc;
            private IDaoAuthor _daoauthor;
    
            public DaoPayroll(PublishingCompanyContext dbcontext, IDaoAuthor daoAuthor)
            {
                pc = dbcontext;
                _daoauthor = daoAuthor;
            }
    
            public async Task<List<DtoPayroll>> GetAll()
            {
                var dtos = new List<DtoPayroll>();
    
                var payrolls = await pc.Payroll.ToListAsync();
    
                foreach (var payroll in payrolls)
                {
                    var dtoauthor = await _daoauthor.Find(payroll.AuthorId); 
                    var dto = new DtoPayroll
                    {
                        PayrollId = payroll.PayrollId,
                        AuthorId = payroll.AuthorId,
                        AuthorFirstName = dtoauthor.FirstName,
                        AuthorLastName = dtoauthor.LastName,
                        Salary = payroll.Salary
                    };
    
                    dtos.Add(dto);
                }
    
                return dtos;
            }
    
            public async Task<DtoPayroll> Find(int id)
            {
                var dto = new DtoPayroll();
    
                var payroll = await pc.Payroll.FindAsync(id);
    
                if (payroll != null)
                { 
                    var dtoauthor = await _daoauthor.Find(payroll.AuthorId);
    
                    if (dtoauthor != null)
                    {
                        dto.PayrollId = payroll.PayrollId;
                        dto.AuthorId = payroll.AuthorId;
                        dto.AuthorFirstName = dtoauthor.FirstName;
                        dto.AuthorLastName = dtoauthor.LastName;
                        dto.Salary = payroll.Salary;
                    }
                    else
                    {
                        throw new Exception($"Author with ID = {id} was not found.");
                    }
                }
                else
                {
                    throw new Exception($"Payroll with ID = {id} was not found.");
                }
    
                return dto;
    
            }
    
            public async Task<DtoPayroll> FindPayRollByAuthorId(int id)
            {
                var dto = new DtoPayroll();
                
                var payroll = await pc.Payroll.Where(a =>a.AuthorId == id).SingleOrDefaultAsync();
    
                if (payroll != null)
                {
                    dto.PayrollId = payroll.PayrollId;
                }
    
                return dto;
            }
    
            public async Task Add(DtoPayroll dto)
            {
                var payroll = new Payroll
                {
                    AuthorId = dto.AuthorId,
                    Salary = dto.Salary
                };
    
                pc.Payroll.Add(payroll);
                await pc.SaveChangesAsync();
    
            }
    
            public async Task Update(DtoPayroll dto)
            {
                var payroll = new Payroll
                {
                    PayrollId = dto.PayrollId,
                    AuthorId = dto.AuthorId,
                    Salary = dto.Salary
                };
    
                pc.Entry(payroll).State = EntityState.Modified;
                await pc.SaveChangesAsync();
    
            }
    
            public async Task Delete(int id)
            {
                var payroll =  pc.Payroll.Find(id);
    
                if (payroll != null)
                {
                    pc.Payroll.Remove(payroll);
                    await pc.SaveChangesAsync();
                }
            }
    
        }
    }
    
    namespace Entities
    {
        public class DtoPayroll
        {
            public int PayrollId { get; set; }
            public int AuthorId { get; set; }
            public string AuthorFirstName { get; set; }
            public string AuthorLastName { get; set; }
            public int? Salary { get; set; }
        }
    }
    

    Monday, July 15, 2019 6:40 AM
  • User1520731567 posted

    Hi kmcnet,

    You could keep in mind this part:

    @foreach (var item in Model.PatientFirstName)
            {
                <tr>
                    <td>
                        @Html.DisplayFor(modelItem => item.PatientLastName)
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.PatientFirstMidName)
                    </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>
            }

    Accoring to your model,your Model.PatientFirstName does not contains PatientLastName,PatientFirstMidName and ID,

    (the property should be included in model,so PatientFirstMidName is also be included in Patient model)

    I suggest you could replace 

    @foreach (var item in Model)
    

    instead of Model.PatientFirstName.

    In addition,Microsoft has a standard template to CRUD named scaffold.
     
    You could follow the steps below:
     
    Right click on Controllers -> Choose Add -> Choose 'MVC5 Controller with views, using Entity Framework', then Add-> Choose the Model you want to add CRUD to in 'Model class', then Add -> The controller with CRUD function is created.
     
    Then you will find Index,Create,Detele,Create...View will be generated automatically.

    Best Regards.

    Yuki Tao

    Monday, July 15, 2019 7:39 AM
  • User1122355199 posted

    Thanks for the response.  I'm floundering in the kiddie pool trying to understand these concepts by applying them to my application.  I have implemented the following:

        public class Patients
        {
            [Key]
            public int ID { get; set; }
    
            [Required(ErrorMessage = "Patient Last Name is required")]
            [StringLength(50)]
            public string PatientLastName { get; set; }
    
            [Required(ErrorMessage = "Patient First Name is required")]
            [StringLength(50)]
            public string PatientFirstName { get; set; }
            public List<Patients> PatientList { get; set; } = new List<Patients>();
        }
        public interface IDaoPatient
        {
            Task<List<Patients>> GetAll();
        }

    However, I am receiving compiler errors with the code:

        public class DaoPatient : IDaoPatient
        {
            private PatientContext pc;
            public async Task<List<Patients>> GetAll()
            {
                var dtos = new List<Patients>();
    
                var patients = await pc.Patients.ToListAsync();
    
                return dtos;
            }
        }

    generates an error "'DaoPatient' does not implement interface member 'IDaoPatient.GetAll()'. 'DaoPatient.GetAll()' cannot implement 'IDaoPatient.GetAll()' because it does not have the matching return type of 'Task<List<Patients>>'." and "The return type of an async method must be void, Task or Task<T>".    I'm not sure how to solve this.

    Wednesday, July 17, 2019 2:10 AM
  • User1120430333 posted

    IMHO, you should be doing something like the below. A plural  naming convention of a class means more that one class/object, ,a List.

    You make the call to the DAL DAO method and comeback wit the dtos. You go into a foreach loop on the dtos, a collection making a new Patient object, populating it from the dto and loading the Patient into Patients the collection. 

    You send the PatientViewModel into the view from the controller, as you see the example you have seen in the thread. 

    return view(new DaoPatient().GetAll());

    For now, put all of these classes in the Models folder just to get it to work, along with PatientDM..cs that the controller is calling. Also for now,  install EF in the MVC project into the Models folder.

    If you want to make a DAL in the Models folder, you can do that too where the DAO stuff goes do it. for now just to learn.

    Keep this in mind,  the EF persistence object is not a VM object. The EF object and the VM object have two different purposes. I  gave you a link about the purpose of using a VM. You can consider the VM kind of like a domain object in a sense.

    https://blog.sapiensworks.com/post/2012/04/07/Just-Stop-It!-The-Domain-Model-Is-Not-The-Persistence-Model.aspx

    Review what is happening in the DM's GetAll() to go get the dtos, which is using an AddRange(); which is just a Linq way for doing a foreach loop, mapping one object to another object  and loading the mapped-to object into a list, doing it on the fly.

    If you have any questions, post.

    publcic class PatientViewModel
    { public class Patient { public int ID { get; set; } [Required(ErrorMessage = "Patient Last Name is required")] [StringLength(50)] public string PatientLastName { get; set; } [Required(ErrorMessage = "Patient First Name is required")] [StringLength(50)] public string PatientFirstName { get; set; } }

    public List<Patient> Patients { get; set; } = new List<Patient>();
    }
    public interface IDaoPatient
     {
            List<DtoPatient> GetAll();
      }
    
    
    public class DaoPatient : IDaoPatient
        {
            public List<DtoPatient> GetAll()
            {
                var dtos = new List<Patient>();
    
                var patients = pc.Patients.ToList();
    
                foreach(var patient in patients)
                {
                   var dto = new DtoPatient();
                   dto.ID = patient.ID;
                   dto.PatientLastName = patient.PatientLastName;
                   dto.PatientFirstName = patient.PatientFirstName;
              
                   dtos.Add(dto)
                }
    
                return dtos;
            }
        }
    public class DtoPatient 
    {
      public int ID { get; set; } 
      public string PatientLastName { get; set; } 
      public string PatientFirstName { get; set; } 
    }

    Wednesday, July 17, 2019 4:18 AM
  • User1122355199 posted

    Thank you so much for all of the help.  I do need some help on several issues.  I agree I just need to get one sample working, but I'm still struggling.  Let me back up a bit.  Since I am trying to learn Entity Framework, and not Data Transportation objects, I elected to adopt a code first approach without any type of scaffolding.  I have an existing database with a table names "Patients".  I set up a class that looks like:

        public class PatientContext : DbContext
        {
            public PatientContext()
                : base("name=PatientConnectionString")
            {
                Database.SetInitializer<PatientContext>(null);
            }
            // This line is giving an error.  Doesn't this need to reference the database table?
            //public DbSet<Patients> Patients { get; set; }
    
        }

    I have the correct connection string to the database set up in the web.config file.  But I'm unclear how the DbSet needs to be set up.

    Next, the code you provided:

        public class DaoPatient : IDaoPatient
        {
            public List<DtoPatient> GetAll()
            {
                var dtos = new List<Patient>();
    
                var patients = pc.Patients.ToList();
    
                foreach (var patient in patients)
                {
                    var dto = new DtoPatient();
                    dto.ID = patient.ID;
                    dto.PatientLastName = patient.PatientLastName;
                    dto.PatientFirstName = patient.PatientFirstName;
    
                    dtos.Add(dto);
                }
    
                return dtos;
            }
        }

    Throws sever errors.  Obviously, pc is not defined for the PatientContext, so I can set the reference, but want to do it correctly.  I am also receiving the error:

    Cannot implicitly convert type 'System.Collections.Generic.List<EntityFramework2.Models.PatientViewModel.Patient>' to 'System.Collections.Generic.List<EntityFramework2.Models.DtoPatient>'	

    I'm trying to learn the pattern rather than slapping some code together that might work, but not be a best practice.  Thank you again for the help.

    Wednesday, July 17, 2019 9:47 PM
  • User1120430333 posted

    Thank you so much for all of the help. I do need some help on several issues. I agree I just need to get one sample working, but I'm still struggling. Let me back up a bit. Since I am trying to learn Entity Framework, and not Data Transportation objects, I elected to adopt a code first approach without any type of scaffolding. I have an existing database with a table names "Patients". I set up a class that looks like:

    If you have an existing DB and you want to use EF code first, then I suggest that you do what is in the link and let the wizard build the model and the DBContext for the time being and learn what it is doing in building the Model objects and the Dbcontext. 

    https://docs.microsoft.com/en-us/ef/ef6/modeling/code-first/workflows/existing-database

    It's the only time I recommend using a wizard under any circumstances. I am not into building such objects manually.

    A lot of EF code first tutorials use the POCO out the gate in their teachings, which is similar to a DTO. But the purpose of the DTO is to travel through the layers, and when the DTO is  prefix or a suffix as part of a class name, one knows what the class is about.

    I am just not a fan of using EF in the ASP.NET MVC project, like so many tutorials teach.  I prefer to implement SoC and keep the controller thin of such code existing in any controller, which is a good practice IMHO, becuase when one doesn't implement SoC then one sees the developer go into the rabbit hole and start abusing the viewbag due to the EF persistence model object is not flexible unlike a viewmodel object.  

    Cannot implicitly convert type 'System.Collections.Generic.List<EntityFramework2.Models.PatientViewModel.Patient>' to 'System.Collections.Generic.List<EntityFramework2.Models.DtoPatient>'

    I thought you were not going to use a DTO? But on the other hand, one doesn't send an EF model object through layers or even through VS project folders like sending an EF model object from the Models folder to a controller as an example, if you're trying to implement SoC. 

    1) You can't make one object be another object (the cast/convert), becuase the class is the blueprint for a given object and what is happening is Patent can't be a DtoPatient. There  has to be a mapping of properties between the two objects.

    2) An object can't be cast/converted across two different namespaces, like xyz.DtoPatient can't be cast to abc.DtoPatient even through they are the same object. 

    It's OO 101 for any OO language platform such as Java or .NET.

    https://alfredjava.wordpress.com/2008/07/08/class-vs-object-vs-instance/

    I guess what I am trying to show is not only how to use EF, but also showing how to use a layered or n-tier  style, becuase using EF is pretty simple. But can one architect that also leads to implementing SoC.

    https://docs.microsoft.com/en-us/previous-versions/msp-n-p/ee658117(v=pandp.10)

    A couple of other things concerning loose coupling. 

    https://www.c-sharpcorner.com/blogs/understanding-interfaces-via-loose-coupling-and-tight-coupling

    https://ardalis.com/new-is-glue

    Can you post your code so that I can see what you have in place so far?

    Thursday, July 18, 2019 2:38 AM
  • User1122355199 posted

    Thanks for the response.  I'm really trying to learn this pattern.  The only thing I'm trying to avoid is using the wizards since I've found them to obfuscate my ability to understand thins.  Here is my entire code to this point:

    The table:

    CREATE TABLE [dbo].[Patients](
    	[ID] [int] IDENTITY(1,1) NOT NULL,
    	[PatientLastName] [varchar](50) NULL,
    	[PatientFirstName] [varchar](50) NULL
    ) ON [PRIMARY]

    Context:

        public class PatientContext : DbContext
        {
            public PatientContext()
                : base("name=KidsConnectionString")
            {
                Database.SetInitializer<PatientContext>(null);
            }
            public DbSet<Patient> Patients { get; set; }
    
        }

    PatientViewModel:

            public class Patient
            {
                public int ID { get; set; }
    
                [Required(ErrorMessage = "Patient Last Name is required")]
                [StringLength(50)]
                public string PatientLastName { get; set; }
    
                [Required(ErrorMessage = "Patient First Name is required")]
                [StringLength(50)]
                public string PatientFirstName { get; set; }
            }
    
            public List<Patient> Patients { get; set; } = new List<Patient>();
        }

    IDaoPatient

        public interface IDaoPatient
        {
            List<DtoPatient> GetAll();
        }
    }

    DaoPatient:

        public class DaoPatient : IDaoPatient
        {
            public List<DtoPatient> GetAll()
            {
                var dtos = new List<Patient>();
    
                var patients = pc.Patients.ToList();
    
                foreach (var patient in patients)
                {
                    var dto = new DtoPatient();
                    dto.ID = patient.ID;
                    dto.PatientLastName = patient.PatientLastName;
                    dto.PatientFirstName = patient.PatientFirstName;
    
                    dtos.Add(dto);
                }
    
                return dtos;
            }
        }

    And DtoPatient:

        public class DtoPatient
        {
            public int ID { get; set; }
            public string PatientLastName { get; set; }
            public string PatientFirstName { get; set; }
        }

    The DaoPatient class is throwing the compiler errors I noted above.  Any help would be appreciated.

    Thursday, July 18, 2019 9:46 PM
  • User1120430333 posted
    In looking at the at the Getall() method,the line should be replaced with the line below.

    var dtos = new List≤DtoPatient>();

    That is what the line should be.
    Thursday, July 18, 2019 10:18 PM
  • User-474980206 posted

    you have several error in your original post.

    1) the view is expecting a Patient object instance, 

    @model Patient

    but you are passing a List<Patient>, so the model is typecast error.

    2. you foreach a string, so item is char (each char of the string)

    
            @foreach (var item in Model.PatientFirstName)
            {

    most lastly you wanted to define the Model as

       @Model List<Patient>

    and foreach the Model, so item is patient.

    @foreach (var item in Model)

    Friday, July 19, 2019 1:13 AM
  • User1122355199 posted

    Thanks to all for the response.  I'm confused on a few concepts.  The DaoPatient makes sense as it is the logic to populate various object.  But why is it necessary to have both a DtoPatient and a PatientVM when they both appear to instantiate ID, PatientLastname, and PatientFirstName.  What am I missing?

    Saturday, July 20, 2019 10:53 PM
  • User1120430333 posted

    kmcnet

    Thanks to all for the response.  I'm confused on a few concepts.  The DaoPatient makes sense as it is the logic to populate various object.  But why is it necessary to have both a DtoPatient and a PatientVM when they both appear to instantiate ID, PatientLastname, and PatientFirstName.  What am I missing?

    The VM is dedicated to the view and the controller when the VM is posted back to the controller, which can have data annotation and business rules applied to VM properties that act in conjunction with the ASP.NET MVC Model state aka Model.Isvalid. 

    A VM doesn't travel between processes or through layers, if you were truly implementing SoC in a Layered style consisting of presentation layer, service layer and data access layer. 

    The SL can implement further business rules if necessary as it acts upon the DTO that is passing through it. But in my usage of the SL, it is the WebAPI client to the WebAPI service.

    https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions-1/models-data/validating-with-a-service-layer-cs

    The DTO travels between processes, layers , has no business logic and just consist of  simple public properties. Also a DTO can be a container for another DTO or DTO(s) in a list and a DTO can be used to shape data.

    https://en.wikipedia.org/wiki/Data_transfer_object

    https://www.codeproject.com/articles/1050468/data-transfer-object-design-pattern-in-csharp

    https://docs.microsoft.com/en-us/aspnet/web-api/overview/data/using-web-api-with-entity-framework/part-5

    Now for instance, you do a get for a Patient object for update, the DTOPatient is populated at the DAL and sent to the presentation layer to populate the PatientVM that is sent into  the  Edit.cshtml for Patientcontroller method working with the PatientVM. The  first thing I do in the view is take ID on the VM for the Patient and save it in a hiddenfield a Hiddenfor() that binds the ID back to the VM ID on the Submit of VM back to the controller action method. From there,  an new DTO is created in the DM object logic, the  corresponding properties of the VM are populated/mapped to the DtoPatient that  is sent back to the DAL to update the existing Patient record in the Patient table based on the DTOPatient information that is populated/mapped to the EF Patient persistence object. If ID > 0 then EF expects the data to update an existing record in the table by its ID, otherwise, if ID = 0, then EF is going to add the data to the database table assigning a new ID to the table record.

    The code example I have been showing has the following architecture:

    1) ASP.NET MVC project aka the presentation layer

        a) It has the VM in the Models folder

         b) it has the DM aka Domain Model object that is the middle man between the controller and the service layer doing CRUD with the database and also working with the VM,  which is all being initiated through the controller action methods

    2) Service Layer that the DM object is calling upon for CRUD operation using HTTPClient() to communicate with the WebAPI service  that is referencing the DAL project.

    3) WebAPI that has refernce to the DAL

    4) DAL that is using the DAO pattern and is doing low-level database CRUD  with the database using EF with a DAO used on a per-table basis.

    And what is common to all the projects is the DTO, becuase the DTO is kept in a classlib project called Entities,  and all the projects have reference to the  Entities project  and they know what the DTO(s) are about.

    Sunday, July 21, 2019 2:04 AM
  • User1122355199 posted

    Thanks so much for the response and the amazing tutorial.  Forgive my ignorance on much of this as I have never delved this deeply into N-Tier.  Please indulge my questions/comments:

    1.  If I understand correctly, the DAO, DAL, and DTO are placed in a separate project called Entity.  I assume this is to create portability to be accessed by other projects that need to access the database.  One entry, one exit.  But doesn't using a Viewmodel that references the same fields as the DTO create second entry point that complicates maintenance?

    2.  What does the role of an interface play in this scheme?  I read the following article:  https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/ but frankly found it confusing.

    3.  What is the best practice for calling the DAL and populating the Viewmodel?

    Thank you for the help and patience.

    Tuesday, July 23, 2019 1:13 AM
  • User1120430333 posted
    1. If I understand correctly, the DAO, DAL, and DTO are placed in a separate project called Entity. I assume this is to create portability to be accessed by other projects that need to access the database. One entry, one exit. But doesn't using a Viewmodel that references the same fields as the DTO create second entry point that complicates maintenance?

    The DAO is an object in the Data Access Layer classlib project that does the low level CRUD operations with a database on a per table basis. The DAO can be using straight up ADO.NET and database command objects for MS SQL Server, Oracle, MySQL or whatever the database technology is about. In-line dynamic T-SQL or (P-SQL Oracle) can be used. It could be a Stored Procedure being used. It could be using  an ORM like EF,  nHibernate or Dapper being used etc. and etc.

    Becuase SoC is being used, the client program like the presentation layer or business logic layer, they  are unware of what technology the DAL is using to work with a given database technology.  The client program could be a mobile program that is consuming an ASP.NET WebAPI, and the client is unaware of what the DAL is using sitting behind the WebAPIOr the solution can be using layered,  n-tier  or one of the other architectural styles. All of it implements SoC, scalability and loose coupling, becuase none of the objects in the layers need to know about the behavior/methods and the code used in the object's method/behavior used in a given layer.

    In ASP.NET MVC, the VM does not travel past the ASP.NET MVC project, and it doesn't travel past the presentation layer aka the ASP.NET MVC project. The Viewmodel is the object that travels between the controller and the view aka the viewname.cshtml with the Domain Object acting as the middle-man between the controller and the view. The VM may not match property per property with a  DTO the VM is working with,  and the VM is a means of keeping property/data state with using hidden properties not seen on the view, but they must be used for other purposes within the MVC solution, like the hidden ID property that must be known on the data of the VM to update an existing record in the database by its known record ID. The VM can have other VM(s) within it, becuase again, the VM is for the MVC view and what is happening at the presentation layer

    On the other hand, the job of the DTO is to travel between layers and processes, the process can be the WebAPI client process  and the WebAPI service process are two different processes, as an example. The VM can't be sent to the DAL and the VM can't  be sent up from the DAL. The VM shouldn't be sent between the  WebAPI client and service. It's the job of the DTO to travel that's the DTO's purpose plain and simple as to where the responsibly falls as to what  object is the traveler.

    The DTO is put into the classlib project called Entities,  and all the other projects/layers in the solution have reference to the Entities project, becuase otherwise, the DTO(s) would have to be duplicated in each layer. If the DTO is changed in the DAL, the DTO must be changed in all the other layers,  instead of just changing the DTO in the Entities classlib project (one spot) that all the other projects have reference to Entities classlib project.

    You can map between VM to DTO or vise versa manually, you can use a library like Automapper the will map the two objects or you could use  the VS plugin  Entity-2-DTO in previous versions of Visual Studio. And of course you will have to map between the DTO and EF entity object and vise versa.

    https://automapper.org/

    https://archive.codeplex.com/?p=entitiestodtos

    https://juristr.com/blog/2012/10/lessions-learned-dont-expose-ef-entities-to-the-client-directly/

    Also, the DTO is an abstraction away from the underlying database technology, becuase all the layers or a WebAPI client sees is the DTO. Also a DTO can be a container for other DTO(s) where one could use other DTO(s) as a result of calling other DAO(s) that contributed their  results to a calling DAO returning its DTO back that had multiple DTO types to the VM that had multiple VM(s) in a VM used by a view working with the result of DTO(s) returned in a single DTO, as an example

    2. What does the role of an interface play in this scheme? I read the following article: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/ but frankly found it confusing.

    The main purpose of an Interface are the following:

    1) Loose coupling vs tight coupling.

    https://www.c-sharpcorner.com/blogs/understanding-interfaces-via-loose-coupling-and-tight-coupling

    2) The 'new' is glue principle and decouple using an Interface

    https://ardalis.com/new-is-glue

    3) Inversion of control and dependency injection

    https://www.c-sharpcorner.com/UploadFile/cda5ba/dependency-injection-di-and-inversion-of-control-ioc/

    You see all 3 being shown somewhat in some of the code I have presented. I have used Unity,  Castel Windsor and .NET Core's IoC. The code being showing to you is a Core solution

    https://www.hanselman.com/blog/ListOfNETDependencyInjectionContainersIOC.aspx

    It's about writing clean code no matter if it's a regular ASP.NET or ASP.NET Core MVC solution.

    https://msdn.microsoft.com/en-us/magazine/mt703433.aspx

    Also Interfaces are used in unit testing and  mocking.

    https://spin.atomicobject.com/2017/08/07/intro-mocking-moq/

    3. What is the best practice for calling the DAL and populating the Viewmodel?

    IMHO, the controller action method  calls a class/object that implements an Interface  in the Models folder that also has the VM in the Models folder. We'll call this SomenameDM aka DM signifies that its a domain model object. SomenameDM has methods/behavior to call the methods in the DAO pattern object in the DAL for CRUD operations for a given table used by EF, which also implements the Interface on the DAO. 

    It means that whatever EF model that is needed should be placed in the Models folder in the DAL project, and the DAO objects  in the DAL have reference to the DAL.Models folder, Of course, you're going to be using the DTO and mapping EF model object to DTO and vise versa for CRUD with the database using EF with the EF model object left at the DAL and the DTO sent through the layers.

    I think you can clearly see what is happening with the controller code I have shown. I also thing you can clearly see what is happening in the DAL with DAO  code I have shown. You can see how the DTO is being used. What you don't see is the Service Layer and the WebAPI code.

    All you need to be focused on is how the perennation layer aka ASP.NET MVC project is referencing the data access layer aka DAL project with both of them referencing the Entities project for the DTO along with what is happening with the objects in the Models folder in the ASP.NET MVC project.

    Again,  EF has to be installed in the ASP.NET MVC project, and EF has to be installed in the DAL project, becuase that is how EF works when the MVC project is referencing the DAL project the has EF in the DAL project.

    MVC is not the only UI design pattern and all of them can be used  with Windows desktop a ASP.NET Web UI(s).

    https://www.codeproject.com/Articles/228214/Understanding-Basics-of-UI-Design-Pattern-MVC-MVP

    Anyone can write some code, but can one architect the solution by using known design patterns and architectural styles.

     https://www.dofactory.com/net/design-patterns

     

    Tuesday, July 23, 2019 4:55 AM
  • User1122355199 posted

    Thank you again.  More stupid question on my part.  Why not, instead of using a DTO which is, if I understand correctly, only GET and SET, implement a class in your Entity lib that uses DataAnnotations and reference it in both the DAL and Viewmodel?  Is it simply separation of concerns or something more?

    Thursday, July 25, 2019 1:51 AM
  • User1120430333 posted

    kmcnet

    Thank you again.  More stupid question on my part.  Why not, instead of using a DTO which is, if I understand correctly, only GET and SET, implement a class in your Entity lib that uses DataAnnotations and reference it in both the DAL and Viewmodel?  Is it simply separation of concerns or something more?

    Now, you can do whatever you want.  But you would be most likely flagged at a code review.  Why not  just use a VM class and send it through the layers, which is not a VM's job of passing data between layers? You can put some business rules, data annotation and anything you want in the class.

    But is it the right thing to do? IMHO it is not the right thing to do. 

    https://en.wikipedia.org/wiki/Data_transfer_object

    <copied>

    The difference between data transfer objects and business objects or data access objects is that a DTO does not have any behavior except for storage, retrieval, serialization and deserialization of its own data (mutators, accessors, parsers and serializers). In other words, DTOs are simple objects that should not contain any business logic but may contain serialization and deserialization mechanisms for transferring data over the wire.

    <end>

    https://martinfowler.com/eaaCatalog/dataTransferObject.html

    https://www.codeproject.com/articles/1050468/data-transfer-object-design-pattern-in-csharp

    <copied>

    DTO (Data Transfer objects) is a data container for moving data between layers. They are also termed as transfer objects. DTO is only used to pass data and does not contain any business logic. They only have simple setters and getters.

    <end>

    https://www.c-sharpcorner.com/blogs/introduction-to-data-transfer-object

    <copied>

    DTO is simple class i.e. only getter setter. There is no business logic in it.

    The majority of applications are using DTOs for passing the data from one layer to another. They are light-weight and are very useful.

    <end>

    Thursday, July 25, 2019 8:43 AM
  • User1122355199 posted

    So this is not an issue of whether it will work, but does it adhere to the design patter.  Am I understanding you.  So placing any type of business logic, such as validation, makes the object something other than a DTO.  So to adhere to the design pattern, you need a VM that mirrors the DTO, but adds things such as validation.  Am I getting the idea?

    The other part I am still trying to understand is the use of interfaces in real applications.  Does the consuming application call the interface?  As far as organizing interfaces, do you typically create one interface per DAO and then place all calls to that DAO within the interface?

    I really appreciate your help.  This has been extremely informative and open my eyes to a new level of programming.

    Saturday, July 27, 2019 12:41 AM
  • User1120430333 posted

    So this is not an issue of whether it will work, but does it adhere to the design patter. Am I understanding you. So placing any type of business logic, such as validation, makes the object something other than a DTO. So to adhere to the design pattern, you need a VM that mirrors the DTO, but adds things such as validation. Am I getting the idea?

    No, in one regard, a DTO coming back from the backend, the persistence layer) doesn't have to be working with a VM at all. The Domain Model object using a DTO for carrying data between another DM object can be done. like PatientDM and DoctorDM  exchanging data between them by usage of a DTO, as an example . The DTO is really an abstraction layer away from the DAL and the underlying database technology that is being used in the DAL, becuase any layers above the DAL all they see are the DTO(s). It means that you could completely change the DB technology used by the DAL, like converting from MS SQL Server to Oracle or even going from EF 6 to EF Core and the layers above the DAL would be unaffected by the change, becuase all they ever see are the DTO(s).

    The DTO can be used to shape data that can be used, like the StudentDTO carrying another DTO within it.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.Dynamic;
    
    namespace MVC.Models
    {
        public class StudentViewModels
        {
            public List<Student> Students { get; set; }
    
            public class Student
            {
                public Int32 StudentID { get; set; }
    
                [Required(ErrorMessage = "Last Name is required")]
                [StringLength(50)]
                public string LastName { get; set; }
    
                [Required(ErrorMessage = "First Name is required")]
                [StringLength(50)]
                public string FirstName { get; set; }
    
                [Required(ErrorMessage = "Enrollment Date is required")]
                [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM-dd-yyyy}")]
                public DateTime? EnrollmentDate { get; set; }
    
                public virtual ICollection<EnrollandCourseViewModel.EnrollandCourse> EnrollsandCourses { get; set; }
            }
        }
    }

    relevant code in the Student domain model object....

    public StudentViewModels.Student GetStudentById(int id)
            {
                var dto = studapi.GetStudentById(id);
    
                var student = new StudentViewModels.Student
                {
                    StudentID = dto.StudentID,
                    FirstName = dto.FirstName,
                    LastName = dto.LastName,
                    EnrollmentDate = dto.EnrollmentDate,
                    EnrollsandCourses = new List<EnrollandCourseViewModel.EnrollandCourse>()
                };
    
                foreach (var dtoec in dto.EnrollsandCourses)
                {
                    var ec = new EnrollandCourseViewModel.EnrollandCourse
                    {
                        Credits = dtoec.Credits,
                        Grade = dtoec.Grade,
                        Title = dtoec.Title
                    };
    
                    student.EnrollsandCourses.Add(ec);
                }
    
                return student;
            }

    relevant code in the DAL and the DaoStudent.

    public class DAOStudent : IDAOStudent
        {
            public DTOStudent GetStudentById(Int32 id)
            {
                var dto = new DTOStudent();
                using (var context = new CUDataEntities())
                {
                    var student = (context.Students.Where(a => a.StudentID == id)).SingleOrDefault();
    
                    if (student != null)
                    {
                        dto.StudentID = student.StudentID;
                        dto.FirstName = student.FirstName;
                        dto.LastName = student.LastName;
                        dto.EnrollmentDate = student.EnrollmentDate;
    
                        var enrolllments =  new DAOEnrollment().GetEntrollmentsByStudentId(id).ToList();
                        var courses = new DAOCourse().GetCoursesByStudentCourseId(student.StudentID).ToList();
    
                        dto.EnrollsandCourses = (from a in enrolllments
                                      join b in courses on a.CourseID equals b.CourseID
                        select new  DTOEnrollandCourse()
                         { Title = b.Title, Credits = b.Credits, Grade = a.Grade }).ToList();
                    }
                }
    
                return dto;
            }

    The DtoStudent had more than itself it was carrying data for with one DTO never used by the VM but was necessary for another purpose. And the DTO wsa being used by a WCF Web  service on the backend so serialization had to be implemented.

    using System;
    using System.Collections.Generic;
    using System.Runtime.Serialization;
    
    namespace Entities
    {
       [DataContract] 
        public class DTOStudent
        {
            
            private DTOResponse dtor = new DTOResponse();
    
            [DataMember]
            public Int32 StudentID { get; set; }
    
            [DataMember]
            public string LastName { get; set; }
    
            [DataMember]
            public string FirstName { get; set; }
    
            [DataMember]
            public DateTime? EnrollmentDate { get; set; }
    
            [DataMember]
            public virtual ICollection<DTOEnrollandCourse> EnrollsandCourses { get; set; }
    
            [DataMember]
            public DTOResponse DtoResponse
            {
                get { return dtor; }
                set { dtor = value; }
            } 
        }
    }
    

     The other part I am still trying to understand is the use of interfaces in real applications. Does the consuming application call the interface? As far as organizing interfaces, do you typically create one interface per DAO and then place all calls to that DAO within the interface?

    In its simplest definition, an Interface implemented by a class/object is a contract that exposés the public properties,  methods and events  that can be seen by the class/object that will use the Interface implemented by the called class/object.

    http://net-informations.com/faq/general/class-interface.htm

    https://deviq.com/interface-segregation-principle/

    Saturday, July 27, 2019 4:15 AM
  • User1122355199 posted

    Thanks again for this amazing tutorial.  This is probably getting to a point where it needs to end and start a new thread, but if I may ask one more very basic questions.  I'm trying to use this design pattern in a basic MVC application.  Here is my code to this point:

        public interface IDaoPatient
        {
            List<DtoPatient> GetAll();
        }
        public class DaoPatient : IDaoPatient
        {
            public List<DtoPatient> GetAll()
            {
                var pc = new PatientContext();
    
                var dtos = new List<DtoPatient>();
    
                var patients = pc.Patients.ToList();
    
                foreach (var patient in patients)
                {
                    var dto = new DtoPatient();
                    dto.ID = patient.ID;
                    dto.PatientLastName = patient.PatientLastName;
                    dto.PatientFirstName = patient.PatientFirstName;
    
                    dtos.Add(dto);
                }
    
                return dtos;
            }
        }
        public class DtoPatient
        {
            public int ID { get; set; }
            public string PatientLastName { get; set; }
            public string PatientFirstName { get; set; }
        }
        public class PatientViewModel
        {
            public class Patient
            {
                public int ID { get; set; }
    
                [Required(ErrorMessage = "Patient Last Name is required")]
                [StringLength(50)]
                public string PatientLastName { get; set; }
    
                [Required(ErrorMessage = "Patient First Name is required")]
                [StringLength(50)]
                public string PatientFirstName { get; set; }
            }
    
            public List<Patient> Patients { get; set; } = new List<Patient>();
        }

    How do I call this from the controller and pass it to the VM?  I can't seem to figure out what to do with this.

    Tuesday, July 30, 2019 8:50 PM
  • User1120430333 posted

    Where the classes located, a folder in the Models folder or in a DAL classlib project  for (DAO)? Where is the DTO located? 

    Tuesday, July 30, 2019 9:43 PM
  • User1122355199 posted

    For simplicity sake and your suggestion, everything is located within the Models folder in the MVC project.  No external libraries. 

    Tuesday, July 30, 2019 10:12 PM
  • User1120430333 posted

    You are missing a class the PaitientDM. It's going to instance a new DaoPatient and uses its GetAll() method() to get the data from the database. It then going to instance a new PahtentVM and retrun the list to the controller that passes the list of PatientVM to the view, which the PaiteintDM method is called GetALL()..

    public IActionResult Index()
            {
                return View(new PatientDM().GetAll());
    
            }
    
    public AuthorVM GetAll()
            {
                var vm = new AuthorVM();
    
                var dtos = new DaoPatient().GetAlll().ToList();
    
               /// of couse you are work with PatientVM and data 
    
                vm.Authors.AddRange(dtos.Select(dto => new AuthorVM.Author()
                {
                    AuthorID = dto.AuthorId,
                    FirstName = dto.FirstName,
                    LastName = dto.LastName
                }).ToList());
    
                return vm;
            }

     This is also assuming that the PatientVM looks similar to the VM 

    namespace PublishingCompany.Models
    {
        public class AuthorVM
        {
            public class Author
            {
                public int AuthorID { get; set; }
    
                [Required(ErrorMessage = "First Name is required")]
                [StringLength(50)]
                public string FirstName { get; set; }
    
                [Required(ErrorMessage = "Last Name is required")]
                [StringLength(50)]
                public string LastName { get; set; }
            }
    
            public List<Author> Authors { get; set; } = new List<Author>();
        }
    }

    This is assuming that the Index.cshtml you are using looks similar.

     

    @model AuthorVM
    @{
        ViewData["Title"] = "Author Page";
    }
    
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Authors</title>
    </head>
    <body>
        <h1>Authors</h1>
    
        <form method="post">
    
            @Html.ActionLink("Create", "Create")
            @Html.ActionLink("Cancel", "Cancel")
    
            <br /><br />
            <table border="1" cellpadding="10">
                <tr>
                    <th>AuthorID</th>
                    <th>First Name</th>
                    <th>Last Name</th>
                    <th colspan="4">Actions</th>
                </tr>
                @foreach (var item in Model.Authors)
                {
                    <tr>
                        <td>@item.AuthorID</td>
                        <td>@item.FirstName</td>
                        <td>@item.LastName</td>
                        <td>
                            @Html.ActionLink("Edit", "Edit", new { id = item.AuthorID })
                        </td>
                        <td>
                            @Html.ActionLink("Detail", "Detail", new { id = item.AuthorID })
                        </td>
    
                        <td>
                            @Html.ActionLink("Delete", "Delete", new { id = item.AuthorID },
                                          new { onclick = "return confirm('Are you sure you wish to delete this author?');" })
                        </td>
    
                    </tr>
                }
            </table>
        </form>
    </body>
    </html>

    Wednesday, July 31, 2019 7:56 AM
  • User1122355199 posted

    Thanks for the response.  More stupid questions, but where does the interface get implemented?

    Thursday, August 1, 2019 12:58 AM
  • User1122355199 posted

    Thanks for the response.  Then where does the interface get implemented?

    Thursday, August 1, 2019 12:59 AM
  • User1120430333 posted

    Thanks for the response.  Then where does the interface get implemented?

    https://www.tutorialsteacher.com/csharp/csharp-interface

    The Interface is implemented on a class 

      public class DaoPatient : IDaoPatient
        {
            public List<DtoPatient> GetAll()
            {
                var dtos = new List<Patient>();
    
                var patients = pc.Patients.ToList();
    
                foreach (var patient in patients)
                {
                    var dto = new DtoPatient();
                    dto.ID = patient.ID;
                    dto.PatientLastName = patient.PatientLastName;
                    dto.PatientFirstName = patient.PatientFirstName;
    
                    dtos.Add(dto);
                }
    
                return dtos;
            }
        }
    namespace PublishingCompany.Models
    {
        public interface IPayRollDM
        {
            PayRollVM GetAll();
            PayRollVM.Payroll Find(int id);
            bool BlnFindPayRollByAuthorId(int id);
            PayRollVM.Payroll Add();
            void Add(PayRollVM.Payroll author);
            PayRollVM.Payroll Update(int id);
            void Update(PayRollVM.Payroll author);
            void Delete(int id);
            PayRollVM.Payroll PopulateSelectedList(PayRollVM.Payroll payroll);
        }
    }
    
    =============================================================================
    
    using ServiceLayer;
    using System.Linq;
    using Entities;
    using Microsoft.AspNetCore.Mvc.Rendering;
    
    namespace PublishingCompany.Models
    {
        public class PayRollDM : IPayRollDM
        {
            private IPayRollSvc svc;
            private IAuthorSvc svcauth;
            public PayRollDM(IPayRollSvc payRollSvc, IAuthorSvc authorSvc)
            {
                svc = payRollSvc;
                svcauth = authorSvc;
            }
    
            public PayRollVM GetAll()
            {
                var vm = new PayRollVM();
    
                var dtos = svc.GetAll().ToList();
    
                vm.Payrolls.AddRange(dtos.Select(dto => new PayRollVM.Payroll()
                {
                    PayrollId = dto.PayrollId,
                    AuthorId = dto.AuthorId,
                    AuthorFirstName = dto.AuthorFirstName,
                    AuthorLastName = dto.AuthorLastName,
                    Salary = dto.Salary
                }).ToList());
    
                return vm;
            }
    
            public PayRollVM.Payroll Find(int id)
            {
                var dto = svc.Find(id);
    
                var payroll = new PayRollVM.Payroll
                {
                    PayrollId = dto.PayrollId,
                    AuthorId = dto.AuthorId,
                    AuthorFirstName = dto.AuthorFirstName,
                    AuthorLastName = dto.AuthorLastName,
                    Salary = dto.Salary
                };
    
                return payroll;
            }
            public bool BlnFindPayRollByAuthorId(int id)
            {
                bool blnflag = false;
    
                var dto = svc.FindPayRollByAuthorId(id);
    
                if (dto.PayrollId != 0)
                {
                    blnflag = true;
                }
    
                return blnflag;
            }
            public PayRollVM.Payroll Add()
            {
                return PopulateSelectedList( new PayRollVM.Payroll());
            }
    
            public void Add(PayRollVM.Payroll payroll)
            {
                var dto = new DtoPayroll
                {
                    AuthorId = int.Parse(payroll.AuthorTypeId),
                    Salary = payroll.Salary
                };
    
                svc.Add(dto);
            }
    
            public PayRollVM.Payroll Update(int id)
            {
                var dto = Find(id);
    
                var payroll = new PayRollVM.Payroll
                {
                    PayrollId = dto.PayrollId,
                    AuthorId = dto.AuthorId,
                    AuthorFirstName = dto.AuthorFirstName,
                    AuthorLastName = dto.AuthorLastName,
                    Salary = dto.Salary
                };
    
                return payroll;
            }
    
            public void Update(PayRollVM.Payroll payroll)
            {
                var dto = new DtoPayroll
                {
                    PayrollId = payroll.PayrollId,
                    AuthorId = payroll.AuthorId,
                    Salary = payroll.Salary
                };
    
                svc.Update(dto);
            }
    
            public void Delete(int id)
            {
                var dto = new DtoId
                {
                    Id = id
                };
    
                svc.Delete(dto);
            }
    
            public PayRollVM.Payroll PopulateSelectedList(PayRollVM.Payroll payroll)
            {
                var dtos = svcauth.GetAuthorTypes().ToList();
    
                payroll.AuthorTypes.AddRange(dtos.Select(dto => new SelectListItem()
                {
                    Value = dto.Value,
                    Text = dto.Text
                }).ToList());
    
                var selected = (from a in payroll.AuthorTypes.Where(a => a.Value == payroll.AuthorTypeId) select a)
                    .SingleOrDefault();
    
                if (selected != null)
                    selected.Selected = true;
    
                return payroll;
    
            }
        }
    }
    

    Thursday, August 1, 2019 5:05 AM
  • User-323149085 posted

    ViewBag.TotalPatients = patients.Count.ToString();

    in your original code : ViewBag.TotalPatients = patients.Count().ToString()

    note Count()

    Thursday, August 1, 2019 12:32 PM
  • User475983607 posted

    Seems like you went down the rabbit hole.  The original error is has to do with the difference between a single type and a collection.  Your View defines a model is that is a single type.

    @model Patient
    @{
        Layout = null;
    }
    

    The View contains logic that tries to loop over a collection.

            @foreach (var item in Model.PatientFirstName)
            {
                <tr>
                    <td>
                        @Html.DisplayFor(modelItem => item.PatientLastName)
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.PatientFirstMidName)
                    </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>
            }

    Well, PatientFirstName is defined as a string.

        public class Patient
        {
            [Key]
            public int ID { get; set; }
            public string PatientLastName { get; set; }
            public string PatientFirstName { get; set; }
        }

    And a string is an collection (array) of characters (bytes) that terminate with a zero.  The foreach is looping over each character in the PatientFirstName string.  That means "var item" is a char.

    I recommend, as I have in your other thread,s to stop using "var" until you get the hang of types.  

    Anyway, the code shown in your first post cannot be the code that is throwing the char error.  The action is passing a list<Patient> to the View but the View is defined as a single Patient.  This causes a dictionary error and execution never reaches the foreach.

    IMHO, the original error does not constitute a switch to the repository pattern.

    Thursday, August 1, 2019 1:46 PM
  • User1122355199 posted

    Yes, I am down the rabbit hole although somewhat willingly, and somewhat based on your previous urgings to adopt more mainstream design patterns.  So I realize this started as a basic Entity Framework question and rapidly evolved into an N-Tier design pattern.  So you are correct in that the solution to my initial problem likely doesn't need reworking into the repository pattern.  Since I am not caught between the two, my thinking was to press forward and complete a working N-Tier repository pattern, using EF, that I can learn from, but perhaps that is a bad idea.  Suggestions?

    Thursday, August 1, 2019 5:41 PM
  • User475983607 posted

    Yes, I am down the rabbit hole although somewhat willingly, and somewhat based on your previous urgings to adopt more mainstream design patterns.  So I realize this started as a basic Entity Framework question and rapidly evolved into an N-Tier design pattern.  So you are correct in that the solution to my initial problem likely doesn't need reworking into the repository pattern.  Since I am not caught between the two, my thinking was to press forward and complete a working N-Tier repository pattern, using EF, that I can learn from, but perhaps that is a bad idea.  Suggestions?

    Pick a design pattern that solves a programming problem.  Never pick a design pattern because everyone is using the pattern.    The repository pattern, while useful, plays a small role in any business application.  I prefer writing services (APIs) which wraps logic rather than a table.  A service's use of interfaces is similar to a repo though.

    I recommend trying to understand the original issue so that does not happen again.

    Thursday, August 1, 2019 6:46 PM
  • User1120430333 posted

    kmcnet

    Yes, I am down the rabbit hole although somewhat willingly, and somewhat based on your previous urgings to adopt more mainstream design patterns.  So I realize this started as a basic Entity Framework question and rapidly evolved into an N-Tier design pattern.  So you are correct in that the solution to my initial problem likely doesn't need reworking into the repository pattern.  Since I am not caught between the two, my thinking was to press forward and complete a working N-Tier repository pattern, using EF, that I can learn from, but perhaps that is a bad idea.  Suggestions?

    You  are not learning N-tier. N-tier is about  tiers of seperation on different computers. At this point, it's about the layered style that you are learning.

    https://docs.microsoft.com/en-us/previous-versions/msp-n-p/ee658117(v=pandp.10)

    <copied>

    N-tier and 3-tier are architectural deployment styles that describe the separation of functionality into segments in much the same way as the layered style, but with each segment being a tier that can be located on a physically separate computer. They evolved through the component-oriented approach, generally using platform specific methods for communication instead of a message-based approach.

    <end>

    Now, you can be like a vast majority of developers that don't know how to use design patterns and architectural styles,  going down  the viewbag rabbit hole,  putting everything in the controller  and using the repository pattern wrongly and going down those rabbit holes, which I cringe every time I  see a developer in the forums  being dragged into them. :)  

    Myself, I don't see it as you're going down a rabbit hole, but this is a learning experience for you. Everything is not about ASP.NET MVC, which is a segment of the total design. The patterns are used in other .NET solutions, like a Windows service, that doean't need  to use a presentation layer, but it may have a business logic layer and the data access layer implemented or even behind a WebAPI or even a WCF service.

    You seem to be having problems with understanding Interfaces. One thing you can do is put a public Test() method in the DaoPatient and see if you can get to Test() without Test() being in the IDaoPatient, the contract for DaoPatient defining what public methods that can be seen by the object that is using DaoPatient. 

    Thursday, August 1, 2019 7:51 PM
  • User1122355199 posted

    Thanks for the response.  I appreciate the learning experience and am really trying to take in all of the lessons.  I'm struggling is a few spots including interfaces, why use them, when to use them, etc.  I am able to access the DaoPatient GetAll() but can't seem to access IDaoPatient.  I haven't figure out how to return either of these successfully to the controller and the view.

    Friday, August 2, 2019 6:52 PM
  • User475983607 posted

    I'm struggling is a few spots including interfaces, why use them, when to use them, etc. 

    An interface is programming construct that allows for grouping common behaviors where the types are different and therefore the implementations must be different.

        public interface IBehavior
        {
            string Talk();
        }
    
        public class Person : IBehavior
        {
            public string Talk()
            {
                return "Hello World";
            }
        }
    
        public class Dog : IBehavior
        {
            public string Talk()
            {
                return "Bark";
            }
        }
            static void Main(string[] args)
            {
    
                IBehavior PersonBehavior = new Person();
                IBehavior DogBehavior = new Dog();
    
                Console.WriteLine(PersonBehavior.Talk());
                Console.WriteLine(DogBehavior.Talk());
            }

    This is a common approach for unit testing. 

    Friday, August 2, 2019 7:20 PM
  • User1122355199 posted

    Thank you.  That clarifies some of my confusions.  But why use this instead of simply implementing a class?

    Friday, August 2, 2019 7:26 PM
  • User1120430333 posted

    Thank you.  That clarifies some of my confusions.  But why use this instead of simply implementing a class?

    It comes back to this that you have seen.

    https://www.c-sharpcorner.com/blogs/understanding-interfaces-via-loose-coupling-and-tight-coupling

    https://ardalis.com/new-is-glue

    <copied>

    Any time you use the new keyword, you are gluing your code to a particular implementation. You are permanently (short of editing, recompiling, and redeploying) hard-coding your application to work with a particular class’s implementation.

    New is Glue. It binds your code to a particular collaborator. If there is any chance you’ll need to be flexible about which implementation your code will need, it’s worth introducing an interface to keep your code loosely coupled. It doesn’t matter what the service is you need – you can always replace it with an interface even if your class is the only one that uses it. 

    <end>

    https://msdn.microsoft.com/en-us/magazine/mt703433.aspx?f=255&MSPPError=-2147217396

    <copied>

    When looking at code to evaluate its coupling, remember the phrase “new is glue.” That is, anywhere you see the “new” keyword instantiating a class, realize you’re gluing your implementation to that specific implementation code. The Dependency Inversion Principle (bit.ly/DI-Principle) states: “Abstractions should not depend on details; details should depend on abstractions.” In this example, the details of how the controller pulls together the data to pass to the view depend on the details of how to get that data—namely, EF.

    <end>

    https://www.codeproject.com/Articles/615139/An-Absolute-Beginners-Tutorial-on-Dependency-Inver

    <copied>

    Dependency inversion principle is a software design principle which provides us the guidelines to write loosely coupled classes. According to the definition of Dependency inversion principle:

    High-level modules should not depend on low-level modules. Both should depend on abstractions.
    Abstractions should not depend upon details. Details should depend upon abstractions.

    <end>

    https://www.tutorialsteacher.com/ioc/ioc-container

    <copied>

    In the previous chapter, we learned how to implement the Dependency Injection pattern to achieve loose coupled classes. IoC Container (a.k.a. DI Container) is a framework for implementing automatic dependency injection. It manages object creation and it's life-time, and also injects dependencies to the class.

    The IoC container creates an object of the specified class and also injects all the dependency objects through a constructor, a property or a method at run time and disposes it at the appropriate time. This is done so that we don't have to create and manage objects manually.

    <end>

    You come to ASP.NET Core MVC, which has a built-in IoC, then maybe you should know a little bit about it before you get there. And besides, every thing I have been talking to you about in general is good OOP programing techniques and practices that can be implemented in any .NET solution using Core or not and it doesn't have to be a Web solution either. Or you goto Core 3.0 Windows Desktop solation, it's beneficial for you understand IOC(s). 

    https://www.c-sharpcorner.com/UploadFile/dacca2/implement-ioc-using-unity-in-mvc-5/

    Friday, August 2, 2019 9:03 PM
  • User1120430333 posted

    Thanks for the response. I appreciate the learning experience and am really trying to take in all of the lessons. I'm struggling is a few spots including interfaces, why use them, when to use them, etc. I am able to access the DaoPatient GetAll() but can't seem to access IDaoPatient. I haven't figure out how to return either of these successfully to the controller and the view.

    And about the above, you can access IDaoPatient by doing something like this.

    var data =  SomeClass( new IDaoPatient).GetSomeData().ToLIat()

    The SomeClass exxpects the DoaPatient class/object to be DI into SomeClass' constructor so that it can be used by GetSomeData(). Of course a new IDaoPatierent is instancing DaoPatient.

    The above can be done during a unit test to satisfy the requirement of SomeClass that expects DaoPatient is going to be injected into SomeClass.

    . You see the constructor for AuthorController(IAuthorDM  authorDM) is specifying that AuthorDM be injected into it and that' s how you do it  by the class's Interface in the constrctor. The AuthorDM was instanced by the Core IoC,  and it was DI into the class by the Core IoC . You see the Core IoC being configured to use the classes and their Interfaces.

    Below that, a VB.NET MVC5 example using the Unity IoC  that is registering the classes along with their Interfaces so that they can be DI into the solution when needed. One set is for the ASP.NET Identity classes and their interfaces as well that are controlled by the IoC

    In the Windows forms MVC solution, by the way MVC started out on desktop solutions well before it got to the Web, you can see the Interface being used, 

    https://www.codeproject.com/Articles/383153/The-Model-View-Controller-MVC-Pattern-with-Csharp

    using Microsoft.AspNetCore.Mvc;
    using PublishingCompany.Models;
    
    namespace PublishingCompany.Controllers
    {
        public class AuthorController : Controller
        {
            private IAuthorDM adm;
            public AuthorController(IAuthorDM authorDM)
            {
                adm = authorDM;
            }
    
            public IActionResult Index()
            {
                return View(adm.GetAll());
            }
    
            public IActionResult Detail(int id = 0)
            {
                return id == 0 ? null : View(adm.Find(id));
            }
    
            public IActionResult Create()
            {
                return View(adm.Add());
            }
    
            [HttpPost]
            public ActionResult Create(AuthorVM.Author author, string submit)
            {
                if (submit == "Cancel") return RedirectToAction("Index");
    
                if (!ModelState.IsValid) return View(author);
    
                adm.Add(author);
                return RedirectToAction("Index");
            }
            
            public ActionResult Edit(int id = 0)
            {
                return id == 0 ? null : View(adm.Update(id));
            }
            
            [HttpPost]
            public ActionResult Edit(AuthorVM.Author author, string submit)
            {
                if (submit == "Cancel") return RedirectToAction("Index");
                            
                if (!ModelState.IsValid) return View(author);
                           
                adm.Update(author);
                return RedirectToAction("Index");
            }
            public IActionResult Delete(int id = 0)
            {
                if (id > 0) adm.Delete(id);
    
                return RedirectToAction("Index");
            }
    
            public ActionResult Cancel()
            {
                return RedirectToAction("Index", "Home");
            }
        }
    }
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Logging;
    using Serilog;
    using ServiceLayer;
    using PublishingCompany.Models;
    
    namespace PublishingCompany
    {
        public class Startup
        {
            public Startup(IConfiguration configuration)
            {
                Configuration = configuration;
                Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(configuration).CreateLogger();
            }
    
            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.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    
                //Domain Model
                services.AddTransient<IAuthorDM, AuthorDM>();
                services.AddTransient<IPayRollDM, PayRollDM>();
                services.AddTransient<IArticleDM, ArticleDM>();
    
                //ServiceLayer
                services.AddTransient<IAuthorSvc, AuthorSvc>();
                services.AddTransient<IPayRollSvc, PayRollSvc>();
                services.AddTransient<IArticleSvc, ArticleSvc>();
            }
    
            // 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)
            {
                loggerFactory.AddSerilog();
    
                app.UseExceptionHandler("/Home/Error");
                
                app.UseStaticFiles();
                app.UseCookiePolicy();
    
                app.UseMvc(routes =>
                {
                    routes.MapRoute(
                        name: "default",
                        template: "{controller=Home}/{action=Index}/{id?}");
                });
            }
        }
    }
    
    Imports System.Data.Entity
    Imports Microsoft.AspNet.Identity
    Imports Microsoft.AspNet.Identity.EntityFramework
    Imports ProgMgmntVB.Controllers
    Imports ProgMgmntVB.Models
    Imports ProgMgmntVB.WebApi
    Imports Unity
    Imports Unity.Injection
    Imports Unity.Lifetime
    Imports Unity.Mvc5
    
    Module ModuleUnity
    
        public class UnityConfig
    
            public shared sub RegisterComponents()
    
                dim container = new UnityContainer()
    
                container.RegisterType(Of IProjectModel, ProjectModel)() 
                container.RegisterType(Of ITaskModel, TaskModel)()
                container.RegisterType(Of IWebApi, WebApi.WebApi)()
                container.RegisterType(Of IModelHelper, ModelHelper)()
    
                'Idenity 
    
                container.RegisterType(Of DbContext, ApplicationDbContext)(new HierarchicalLifetimeManager())
                container.RegisterType(of UserManager(of ApplicationUser))(new HierarchicalLifetimeManager())
                container.RegisterType(of IUserStore(of ApplicationUser), UserStore(of ApplicationUser))(New HierarchicalLifetimeManager())
                container.RegisterType(of AccountController)(new InjectionConstructor())
    
                DependencyResolver.SetResolver(new UnityDependencyResolver(container))
    
            End sub
        
        End Class
    End Module
    

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Saturday, August 3, 2019 8:16 AM
  • User475983607 posted

    That clarifies some of my confusions.  But why use this instead of simply implementing a class?

    Interfaces are another tool in your toolbox.  The construct is very common and a subject that I recommend taking the time to learn.

    Below is a very common pattern where the a business logic class can accept any type that implements IBehavior.

        public class BusinessLogic
        {
            private readonly IBehavior _behavior;
            public BusinessLogic(IBehavior behavior)
            {
                _behavior = behavior;
            }
    
            public string Talk()
            {
                return _behavior.Talk();
            }
        }

    Implementation.

            static void Main(string[] args)
            {
                BusinessLogic bl1 = new BusinessLogic(new Person());
                BusinessLogic bl2 = new BusinessLogic(new Dog());
    
                Console.WriteLine(bl1.Talk());
                Console.WriteLine(bl2.Talk());
            }

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Saturday, August 3, 2019 12:52 PM