Asp.Net Core 2.2 MVC Development Notes

  1. Good Resource to Read about MVC, Dot Net Architecture
  2. .Net Core 2.2 has emphasized to use Dependency injection Loosely coupled applications
  3. Dot Net core 2.2 has implemented the use of Middleware components that is responsible for HTTP requests. Research more about the .Net MiddleWare.

    To Add Client-Side Library to Dot Net Core 2.2 Project
  4. Click on the project solution and navigate to add => Client-Side Library (You can now search for a library you want to bring in the project)

    Developer Exception Page
  5. To enable plugin UseDeveloperExceptionPage Middleware in the pipeline.

    Development Environment Variables
  6. Development, Staging, and Production
    -You can set the environment variable on the Operating System level and the IIS will pick the variable from the system. This is helpful when deploying to different servers used for production.
    -Run time environment defaults to "Production" if not set

    MVC
  7. Controller, View, and Model
    - The model consists of a DTO class, an IRespository Class (acts as an Interface, which brings good practice in case you want to change members in a DTO. It manages the DTO class data) and IDTO class that inherits from IRespository class.
    [NB] This methodology reminds me of College Watch this video
    -By defining interfaces, allows developers to use dependency injection which leads to loosely coupled and easily testable
    - The use of Controllers reminds me of stackoverflow.com writing mechanism, http://domainName.com/controllerName/ActionName/Paremeter
    In the Controller action function then you can call the Model and implement the logic. Sweet and Simple.

    Start-Up Class
  8. This class is a source of truth of all dependency like, for example, if you want to add MVC dependency to your project, then Start Up class will be the place to add that IService.
    - There is a function called Configure(IApplicationBuilder app, IHostingEnvirment env) this function and it's code, passes the HTTP request to a next app.Use the declaration. If the first defined app.Use does not have the response for an HTTP request, then it passes on to another app.Use to process the request.
    - If you want to use a service first add the service in ConfigureServices and then add app.UseTheServiceYouAdded
    -Differences from AddMvc vs AddMvcCore is that the MvcCore has a controller class if you inherit a controller class in your class and then do, this and dot (this.) you will have a much bigger API with functions you can use like "return JSON data"
    -The differences are that addMvc adds all required services automatically without defining them in the ConfigureServices block, on the other hand, addMvcCore will only add few services and require you to define what services you want to use in the ConfigureServices block.

    Model
  9. In MVC, Model classes do not have to be necessarily in the Models Folder but it is considered a good practice.
    - type prop and press the tab key twice, it will generate a property variable with get; set; 
    - The model contains the object properties and logic
    -Create an Interface class with a name of IObjectRepository that will be used to inherit by Another Real Repository Class that will contain actual functions. The Actual Repository class will use the DTO class object. The Interface will define the functions like RetrieveEmployee or SaveEmployee in form of an Interface. e.g. Employee GetEmployee(int Id);
    -The RealActual Repository Class will inherit the IObjectRepository and then implement its functions.
    -The reason why the Interface is used is that it allows developers to use dependency injection which is a big deal in Dot Net Core. It allows easy changing of properties, unity testing and many more.
    - When the IObjectRepository and RealActualRepository are implemented (coded), then in order to use the IObjectRepository, in the Controller, create a Constructor in the Controller you want to get access to RealActual Repository (This is the way to inject that IObjectRepository Interface) and inject the IObjectRepository into the Controller Constructor. The instance initialization code will be highlighted then it will advise you to create a private variable of type IObjectRepostory for read-only.
    -After the dependency injection code is implemented in the constructor of a Controller then move to the function/method you want to use the object in, e.g. public void index(){use IObjectRepository instance.}
    -The interface does not do any work but only define properties or Interface functions, the work is done in the RealActualRepository

    ASP.Net Core Model Binding
  10. To bind the data in the HTTP request to the Controller Action method parameters, the Model binding looks for passed data from the HTTP request in the following: 
    -Form values
    -Route values
    -Query Strings

    Dependency Injection
  11. When we injected the IObjectRepository into a constructor, we noticed that the "new" keyword wasn't used. If the service wasn't added into the IServiceConfigure function in StartUp class, then you will receive the error because the MVC application does not know about the IObjectRepository. Watch this Video
    -[NB] Navigate to Start-Up Class and find ConfigureServices(IServiceCollection services) function and register your IObject Interface, using services.AddSingleton function. When you use services.AddSingleton
    -The reason for not using a "new" keyword is because it creates a tightly coupled system. In the case of adding more properties, you only change in one place.
    -If you had to swap the implementation with another RealActualRepository class, it will be easy with dependency injection in place.
    -When the singleton instance is created, all HTTP request uses that one single instance throughout the application lifetime.
    *Similar functions: AddSinglton(), AddTransient() and AddScoped()
    -It is a good practice to define a dependency class instance a ReadOnly because it prevents accidentally from assigning another value to a class instance.

    JSONResult
    - In the Controller, you can choose to return the whole object of the DTO in form of JSON by prefixing the type of the function to JSON and add (return Json(ObjectName)) inside the function.
    - This way, you can use the Razor Rendering Engine to call the function that returns JSON data. Brilliant isn't it. The way you would call a function from Razor or JavaScript/Web Assembly is by calling https://www.domainName.com/ControllerName/FunctionName

    XML Data Format
    - Likewise, if you want your application to accept data type specified in HTTP Header Request, then the Services for XML should be added in the Start-Up class for an application to be able to return XML Data format. You do this by chaining services.AddMVC().AddXMLSerializerFormatters() method.

    ViewResults (Will automatically look for a corresponding View with a function/Action Name in the View folder)
    - In the controller Action Method, you can choose to return a ViewResult, a return statement will look like this: 
    public ViewResults NameOfFunction(){
    TypeOfObjectInstance model = IRepositoryInstanceYouDeclaredInContructorThatIsReadOnly.NameOfActionYouWantToAccess.
    Return View(model);
    }

    _ViewImports partials 
    - This partial is used to inject any dependencies that will be used in the front-end. It makes any dependencies injected in it available to other Views. This comes in handy when you scaffold a new MVC component and would want to reference Class files in NewModels Folder instead of Models folder. Be careful though, you might get a CS0234 Error that comes when Razor Engine compiles files, to resolve this error, research on how to clear Razor Cache files. Discussion is beyond the scope of this document.

    Controller
  12. If you want to specify an Action Attributes [HttpGet] and [HttpPost] on the same function, you could type [AcceptsVerbs("Get","Post")]
    - C# 6 string interpretation $"Some text here {BindData} some text in here";

    Views (is file with .cshtml file extension)
  13. The View method is provided by the Base Controller Class
    -All the Views that belong to a Controller lives in a Folder that has the same name as a Controller, e.g. Views belonging to Home Controller will be in a View/Home Folder. The System looks for a View with the Action or Method name and returns it. In some cases, the Controller class will determine the name of the view to return.
    - In the Controller function/Action, the Employee Object or Object instance was then passed to the View, the View will utilize that object for binding data purposes. (It is a content Layer, the heavy computing and Logic should be implemented in the Controller)
    -The view is the data presentation layer. MVC looks for a View that has the same name as an Action Method.
    -The View function/method from MVC takes more parameter, if you want to specify the name of the View in the Views Folder instead of using a default one (same as the name of an Action method in the Controller), you can specify the name of the template to use.
    - You want to use a Razor template that is in another folder, specify in the View("../FolderWhereTheTemplateIs/NameOfTemplete") because by default, MVC looks for a template in a Controller View Folder.
    -[NB] If you use a relative path in the Controller Return View("../etc") the file extension of cshtml is not required or needed.

    Pass Data to View from Controller
  14. Data can be passed to the Model from a Controller by ViewData, Strongly Typed View or View Bag
    ViewData => is a collection of weakly typed objects (dictionary)
       The way to pass along various data to the view from the controller is by creating an object of ViewData["Key"] = InstanceOfAnObject;
    - just like embedded Ruby in Ruby and Rails, you can embed c-sharp code by indicating to Razor Engine that you are now switching from using HTML to C-Sharp code by starting a line of C-Sharp code with "@" symbol. In this case, you can access ViewData value by typing @ViewData["Key"] in the View template.
    -If you are accessing an Object from the ViewData you will have to cast using an "at" then the intelisnse should guide you afterward. Video Here

    ViewBag => Is a wrapper to ViewData API, using ViewBag the key data is dynamic e.g. ViewBag.Key = AssignObject
       In ViewBag, you don't have to cast data of type String or an Instance of an Object, it automatically cast that for you. Accessing data from ViewBag will be simply as typing @ViewBag.Key.WhateverPropertyIsAvailable. Both ViewData and ViewBag creates loosely typed data.

    -Strongly Typed View  (Best Way) => Is when you pass the whole model object as an argument in the View(object instance). This is strongly typed as nothing is dynamic in the Object instance.

    -The way you access data passed in by a View(ObjectInstance) in Razor View is by typing @Model.PropertyName
    [NB] To make a View a strongly typed so that you can have the intellisense when accessing the data, include: @Model Namespace.Model.NameOfModel this way you don't make mistakes when binding data, properties will show up when you type a dot symbol.

    View Model (DTO)
  15. Sometimes a Model may not contain all the data a View needs, however, a View Model may contain all the data a View needs.
    - You do this by creating a folder from the root project called ViewModel and then creating a C-Sharp class file called NameOfControllerNameOfActionViewModel.cs in this case this class is also called Data Transfer Object (DTO).
    - Type prop + tab and tab to generate a property of a type ObjectModelInstance
    - In the DTO, is where you will put all the data the View would need to operate, let's say the page title, etc.
    - You can use this DTO to package the data and use the instance the main controller that does Business logic and pass the DTO object to the View. this way, the view can then loop or access the Data Model it has access to. 

    List View
  16. When you add another function/method in the Object Interface class, you will have to re-Implement the interface again in those classes you inherited the interface.
    -For example, if you create a function that returns a public IEnumerable, the way you include a model type in the View index.cshtml is by specifying a type of data you defined in the function, in this case, it is IEnumerable.

    Layout View
  17. Use layouts to style your page

    AddSingleton vs AddScrop in Start-Up Class (HTTP POST in Controller)
  18. To be able to handle a post request from a button in View UI, the controller has to have a [HTTPPOST] directive on top of a function that handles the post method.
    - The name of the Action in the Controller matters, it goes to the View Folder and finds a View with a name like an Action and returns it. That is why it is important to prefix the HTTP method on top the function in the Controller.
    Post Data to Controller: you can include @Inject IArticleRepository _iarticleRepository in the form View to be able to depend on that Interface. Video Here
    - Using an AddSingleton only uses one single instance throughout the application session while AddScope instantiates different services for every HTTP request. A user has to wait for another session to issue an HTTP post request.

    Entity Framework Core
  19. In Asp.net Core EF Core is a complete write of Entity Framework ORM (Object Relational Mapper)
    - works cross-platform, open-source and support Code-First approach and Database-First approach.
    - In the Code-First approach, the classes (domain classes and DB Context classes) are first created, EF Core then creates the Database.
    - In the Database-First approach, EF Core generates domain class and DB Context from the already created schema. It is able to use various database providers e.g. SQL or MySQL database providers.
    - If you create/add a class library project in your add main asp.net Core project and navigate to NuGet Packages to install Microsoft.EntityFrameworkCore.SqlServer all the required dependencies will be installed in one installation.
    - Reverse Engineer your models by generating models based on your existing database:
          -run: scaffold-DbContext "YourConnectionStringComesHere" Microsoft.EntityFrameworkCore.SqlServer -OurputDir YourFolderOfChoice.

    Data Access Using DBContext in Entity Framework Core
  20. Create a class called ApplicationdBContext and inject an instance of a DB Context in the constructor, if you are using scaffolding mechanism built into MVC Core then this process will be done for you depending on how you first created the project.
    - The DBEntity Class includes a DbSet function that sets and saves the new objects of a Model Class.
    - It then uses LINQ to query against the DbSet object that translates C-Sharp code into T-SQL to communicate with the database.

    Repository Pattern in ASP.NET Core
  21. It is an abstraction to the Data Access Layer, it hides how the data is being retrieved from the database
    - In order to use an SQL Database in the Repository Class, register the Service with an AddScoped function in the Start-Up Class in Asp.Net Core. The reason why we should use AddScoped instead of AddSingleton function is that we want the exitance of the Service to be available to the entire scope of an application within the context of an Http Request.
    - The benefit of using a Repository pattern is that the code is cleaner and easy to use.

    Entity Framework core Data Migration
  22. Migration keeps the database schema and application model classes in sync
    - After coding Model classes inside the application and configuring all the business logic, if you are using code first approach of Entity Framework then you will need to migrate the Model classes into database tables.
    - To run data migration open on Dot Net CLI or Package Manager console and type: Add-Migration nameOfTheMigrationCouldBeAnything
    - To actually create the tables EF Core type: Update-Database (Updates the database to a specified migration) If the migration is not specified the latest migration will be used.
    - Commands for Entity Framework Core are
    get-help about_entityframeworkcore  (Provides entity framework core help)
    - When you added a Model in the Asp.Net Core, a DBSet property was set in ApplicationDBContext and when you run Add-Migration the EF Core creates the table in SQL server with the name set in ApplicationDBContext.

    Seed a Database Table in Entity Framework Core
  23. You can seed the table in the database with initial data by overriding the onCreate function in the ApplicationDbContext class, just type override and the intellisense will appear with functions to override.
    - In the overridden method in the ApplicationDbContext class, add objects you want to be inserted into the database
    - After the objects have been added, navigate to the Package Manager and add a data Migration by typing: Add-Migration nameOfMigrationAnythingYouWant
    - After the migration is added or generated and stored in the Migration Folder in your project, type Update-Database and the database should be seeded with new dummy data you specified in the override method.
    - If you made a mistake when you seeded the database, You can make the changes and then add another migration with a different name and Update-Database
    - You can put all your dummy data in a separate class and use the extension method to utilize the class with seed data.

    Keeping Domain Models and Database Schema in Sync


  24. Razor
  25. Unlike HTML Razor comments are not sent to the client
    - Why use tag helpers instead of just writing HTML? Picture this, when you develop your application with hard-coded links and HTML linking to specific Controller, when you change the routing of a specific Controller all the code in Views will break. By using Tag Helpers, your application won't break.
    - Image tag helper inserts a hash into your image URL to prevent cross-site scripting. If you include asp-append-version=true to the link of the image, the has will be appended. The hash prompts the browser to reload the image when the image on the Server changes.


    [Note] Type prop + tab and tab, Visual Studio will generate a property automatically in a c-sharp class
    - The beauty of using Interfaces Repository is that you create many classes that derive or inherit from one single Interface and when it comes time to change or add implementation is done in one interface.

    Identity
  26. Think of ClaimsPrincipal as a signed-in user

    Authorization
  27. Identifies who the user is and what they can or can not do
    - When you prefix the Action in the Controller with an [Authorize] attribute, when the user is not logged in and try to access the page the MVC framework redirects them to the login page and when a user logs in, they are redirected to the URL they first wanted to go.
    - Just like you could prefix the Action method with a [Authorize] for authorization, you could also prefix on the Controller Level to restrict access to the controller unless you are authenticated.
    - [AllowAnonymous] will allow access to unauthenticated users.

  28. Helpful Websites
    - This web app will help you understand where the classes have been moved to in a version of ASP.Net Core LinkHere
    - Further Reading: This is a helpful blog LinkHere

  29. Bonus
    - Use the keys Ctrl + Shift +F simultaneously to bring up Find and Replace ( this very handy when it come so refactoring code )
    - When working in the VS Code and you find yourself editing thousands of lines of code. There is a feature in VS Code that allows you to select the same word at once and edit, that appears in multiple areas in one file. Hold Ctrl + D several times and all words be edited at once.
    - On Windows hold Ctrl + Shift + Alt then down-arrow to select multiple lines of code and then add or edit. This is a life server when you find yourself editing multiple lines of code.
    - If you start your Dotnet core 2.2 web app using Powershell and commands: dotnet run, the website does not break if one file has an error. This behavior is seen when developing in PHP, Rails as well. Unlike developing in ASP.Net websites developing in core 2.2 seem to be easy and forgiving.

    [Questions] 

    - Does Razor Engine have Controls like it is in Asp.Net Standard?
    - How does Profiles API work in MVC Core, asp.net Core 2.2