Skip to content

This repository is meant to show the different ASP.NET Core MVC features I learned and implemented as samples.

Notifications You must be signed in to change notification settings

Alex-Dinu/Demo-Code

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

63 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Demo Code

The purpose of this repository is to showcase various tools, development principles, solution architecture and the usage of 3rd party tools that demonstrate my experience. This demo code solution uses .NETCore 2.2. It is built in modules, so it does not implement any architecture design ot principle.

Table of Contents

  1. Technologies and tools
    1. Clean Architecture
    2. SOLID Principles
      1. Single Responsibility Principle
      2. Open Closed Principle
      3. Liskov Substitution Principle
      4. Interface Segregation Principle
      5. Dependency Inversion Principle
    3. Async
  2. .NET Core
    1. Tools and packages
      1. Logger
      2. Entity Framework Core
      3. Automapper
      4. XUnit
      5. Swashbuckle
      6. MiniProfiler
  3. MVC
    1. Middleware
      1. Request\Response logger
      2. Unhandled Exception middleware
    2. Responses
      1. Return types
    3. Validators
      1. Custom Validators
      2. Remote Validations
  4. JQuery
    1. Closures
    2. Promises
    3. AJAX calls
  5. JQuery UI
    1. Drag\Drop
  6. TODO

Technologies and tools

Clean Architecture

Although the solution is not strictly Clean Architecture, it does implement the basic principles. I did take some shortcuts in order to make it easier to follow the code and try it out. One of the rules of CA is a strict direction of data flow and to use interfaces when communicating the opposite direction.

One way to implement these rules, is to use 3rd prty packages that reduce the amount of code you have to write. An example of such a package is documented below (Automapper).

SOLID Principles

Single Responsibility Principle

Each software module should have only one reason to change.

This link demonstrates the smell and this link demonstrates the fix.

Open Closed Principle

Software entities should be open for extension, but closed for modification

There are at least three wyas to resolve the OPC:

  1. Using parameters.
  2. Virtual methods.
  3. Factories. This option can be expanded to use interfaces instead of abstract classes and reflection to eliminate the conditional code.

Liskov Substitution Principle

Subtypes must be substitutable for their base types

There are at least three smells that can be used to identify when we break LSP:

  1. The need to check the type,
  2. The need to check for nulls,
  3. We don't implement the whole contract and require to throw a NotImplementedException.

The forst two break the Tell, Don't Ask Principle. This link shows some possible fixes.

Interface Segregation Principle

Clients should not be forced to depend on methods they do not use.

Closely related to LSP, this code adds another smell that breaks ISP. And here is a possible fix.

Dependency Inversion Principle

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

This code shows us the problem. and a possible solution. One thing to note, .NET Core has a built-in IoC(Inversion of Control) container for us to use.

Async

To view the code and execution, make the NetCoreAsync project as the startup project. It uses a simple breakfast preparation steps to illustrate how async helps you prepare it faster and how it helps the code be more scalabale.

In Program.cs, you will see the natural regression from non-async code to an async code: Uncomment each PrepareBreakfast call to see the execution.

  • sync.PrepareBrakfast() is a non-async call.
  • async.PrepareBreakfast() shows you how to convert the non-async code into async code.
  • async.PrepareBreakfast2() groups together related methods to make the code more readable.
  • async.PrepareBreakfast3() adds the WhenAll functionality to improve the readbility and async controll better.

.NET Core

Tools and packages

Logger

Microsoft introduced ILogger to help us log information. There are numerous other 3rd party packages that extend ILOgger and add additional functionality. I use Serilog in order to help me log information and errors in JSON format in a daily rolling file with a max size.

The Infrastructure.Log project does it all. It is referenced by each project that requires to log something. I set up some properties in Startup.cs in a private AddSerilogServices() method. We are also loading the class as scoped. The reason being is that it also generates a unique ID for each http request, so when we log the events and errors, we can easily search by the ID and order by the date so we can see a complete picture of a specific request. You can vew the code here.

Serilog has a rich number of supporting packages. The following NugetPackages are used:

  • Serilog.Exceptions which makes it easier to log exceptions and their properties.
  • Serilog.Settings.Configuration is used to read some configuration settings
  • Serilog.Sinks.Async is used to log asynchronously
  • Serilog.Sinks.RollingFile allows me to easily setup the rolling log file.

Notice that we are sending a parameter type to the logger methods. This allows us to send in as many parameters as are needed to be logged as illustrated by the following interface contract:

void LogError(Exception ex, params object[] data);

Entity Framework Core

Being a .NETCore solution, EFCore is being used. While most of the demos do not require a database, some calls under the EFCore menu item do, so you would need to perform the following steps:

  1. Install the Wide World Importers database
    1. Download the WideWorldImporters-Standard.bak backup database in order to restore it from this site.
  2. Compile the application stored procedures in Infrastructure.Database.SQL.StoredProcedures
  3. Update the EFCore connection string in the appsettings file.

AutoMapper

AutoMapper is a library I use to map the different data objects that are passed between the different layers in Clean Architecture solution. Mapper rules are setup in WebUi.Shared.DataMapper class and is added as a service in Startup.cs.

XUnit

I use XUnit to run my tests. It has a few nice features:

  • Useage of constructors instead of initializers
  • Test fixtures that are loaded once and used in every test
  • Pass in data as parameters to test cases that will allow you to run the same test with multiple data elements. You can see this in this test. OrderAuthorizationTests() expects two classes that will return the parameters the test method requires.
  • Will start an Http Client based on the startup settings.

Swashbuckle

This package automatically generates json and a UI representation of your services. You can expand it by adding .NET XML documentation to the properties and methods and creating test data for the models. All the settings are in one class that is referenced in the startup class. You can also document sample data

To get the JSON code that can be used to communicate with consumers, add the following to the end of the home URL: /swagger/v1.0/swagger.json e.g. http://localhost:62681/swagger/v1.0/swagger.json

To view the UI, add the following to the end of the home URL: /swagger/index.html e.g. http://localhost:62681/swagger/index.html

MiniProfiler

MiniProfiler helps us log performance counters to better detect any performance issues. It's a configurable set of functions that display data on an MVC page, store data in a database, implements role security and hooks into Http and EF Core calls to supply additional details like the SQL statement or Http details.

Once you install the related Nuget packages and configure them in the Startup, all you need to do is add it to the UI. You can see the output from the Misc\MiniProfiler menu.

MVC/API

Middleware

We use middleware to manage the request pipeline. Any classes that the middleware require need to be added to the container in Startup.cs and we need to also add the middleware to the application also in Startup.Configure() method.

Request\Response logger

This middleware automatically logs the request values and the response, It can be found here

Unhandled Exception middleware

This middleware will catch any unhandled exceptions, build a custom response and return it so we won't return any secure information just in case someone missed a try\catch.

Responses

Return types

We can now explicitly return the type of the action. In the past, we used to return ActionResult, but now we can explicitly say what the type is, e.g. Task<ActionResult>.

Validators

Custom Validators

I added a custom validator attribute to showcase how we can pass the existing property we need to validate and anotherproperty value into the validator. The validator code can be found here and is used as follows:

    [DisplayName("Preferred Name")]
    public string PreferredName { get; set; }
    [DisplayName("Logon Name")]
    [ValidLogon("PreferredName", ErrorMessage = "Invalid Logon")]
    public string LogonName { get; set; }

As you can see, we are validating the LogonName against the PreferredName.

Remote Validations

Remote validations perform an asynchronous call to the server to perform a validation while the client continues to fill out the form. For example, if an email address has to be unique, once they tab away from the input, and continue to fill out the form, an AJAX call is made to make sure the field is not already in use. The validation code can be found here at the end in the PhoneNumberIsUnique() method and is setup as an attribute on the property:

    [Remote("CheckIfEmailAlreadyExists", "Employees", ErrorMessage = "Email already exists")]
    public string EmailAddress { get; set; }

The first parameter is the action an the second is the controller.

JQuery

Closures

This is the source code. You can see it in action by running the site and selecting Closures from the JQUery menu.

Promises

This is the source code. You can see it in action by running the site and selecting Promises from the JQUery menu.

AJAX calls

This demonstrates a simple AJAX call to get some results from an API call. You can look at the code here and see it in action by running the site and selecting AJAX from the JQUery menu.

JQuery UI

Drag\Drop

This code demonstrates the drag\drop features, append, JQuery data and and how to manage JSON data.

TODO

The following section lists additional code I want to add to the solution.

About

This repository is meant to show the different ASP.NET Core MVC features I learned and implemented as samples.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages