There is a pathology laboratory in the city and they owned multiple branches over the state. Some of the branches are running in own premises and some of the branches running in third party buillding owner. When they plan to open a new outlet, they need to agreement with the building owner with terms and conditions.
All these points are mentioned in the agreement paper and duly signed each party, then they keep the physical document in separate folder.
Let us start with blank .Net solution, then add the Web project and class library project
Open Visual studio and select "create a new project"
select "Blank solution"
Provide the solution name
Add new MVC web project
Provide the project name and ensure the folder structure
Select the web project type
Web project folder structure
Add new class library project
Select the "Class Library(.Net Standard)" from the list of project template
Provide the class library project name and ensure the folder structure
Ensure the project with folder structure
Run and test the project
Create the Database - Code First Approach
Enter the database name and select the location where to save the database in your system
Ensure the database has been created.
Install "Entity Framework"
Why Entity Framework - The entity framework is a ORM tool which is used to interact with SQL server database from .Net application.
Ensure the "Entity Framework" reference added the project
Add the database connection string in "Agreement.Domain" project
<connectionStrings>
<add name="AgreementDB" connectionString="Data Source=localhost;initial Catalog=AgreementDemo;user id=sa;password=****"
providerName="System.Data.SqlClient" />
<connectionStrings>
Add the database connection string in "Agreement.WebUI" project
Create the DbContext class
Create the DBInitializer class
Add the Agreement.Domain project reference with Agreement.WebUI
Define the "Agreement" class in "Agreement.Domain"
using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace Agreement.Domain { [Table("Agreement")] public class AgreementData { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] [Required] public int AgreementId { get; set; } [Required] [Column(TypeName = "VARCHAR")] [MaxLength(250)] public string PremisesAddress1 { set; get; } [Column(TypeName = "VARCHAR")] [MaxLength(250)] public string PremisesAddress2 { set; get; } [Column(TypeName = "VARCHAR")] [MaxLength(250)] public string PremisesAddress3 { set; get; } [Column(TypeName = "VARCHAR")] [MaxLength(250)] public string PremisesCity { set; get; } [Column(TypeName = "VARCHAR")] [MaxLength(10)] public string PremisesPincode { set; get; } [Required] [Column(TypeName = "VARCHAR")] [MaxLength(1000)] public string PremisesDescription { set; get; } [Required] [Column(TypeName = "VARCHAR")] [MaxLength(250)] public string PaymentMethod { get; set; } } }
Define the "AgreementData" as member of DbContext class
Access the "AgreementData" from Home controller
Check your database
I add two more fields in the domain model "AgreementData"
[Required]
public DateTime EntryDate { get; set; }
[Required]
[Column(TypeName = "VARCHAR")]
[MaxLength(100)]
public string UserId { get; set; }
I run the application. The application throws the exception. Refer the below image.
There are three migration commands
Migration command example
Run the following command at package manager console
Enable Migration
Add Migration
The add Migration command will ask the "Name" which is called as "migration name". A class will be created using the "migration name" in the migration folder. Refer the below image.
New Migration class will be added in the migration folder.
Content of migration class
Update database
After the "Update database" command execution completed,
Open the following files and delete the content
Open the layout page and change the application name. Go to Views->Shared->_Layout.cshtml
Run and test application and refer the following image
Layout page is just like master page which provide consistent appearance for all pages. The file should be placed in "Shared" folder. So all views will use this page and we have so specify the layout name in all view files.
ViewModel is a class that contains the fields which are represented in the strongly-typed view. It is used to pass data from controller to strongly-typed view. When we use view model as parament in post action method, the html input control value passed to view model. This is called as "Model Binding". The following line specify the layout page.
Layout = "~/Views/Shared/_Layout.cshtml";
public class NewAgreementViewModel
{
public int? AgreementId { get; set; }
[Display(Name = "Address1")]
[Required]
[StringLength(250)]
public string PremisesAddress1 { set; get; }
[Display(Name = "Address2")]
[Required]
[StringLength(250)]
public string PremisesAddress2 { set; get; }
[Display(Name = "Address3")]
[StringLength(250)]
public string PremisesAddress3 { set; get; }
[Display(Name = "City")]
[Required]
[StringLength(250)]
public string PremisesCity { set; get; }
[Display(Name = "Pincode")]
[Required]
[StringLength(6)]
public string PremisesPincode { set; get; }
[Display(Name = "Detail of the Premises")]
[Required]
[StringLength(1000)]
public string PremisesDescription { set; get; }
}
Create a new empty controller and the controller name should be "DocumentController". Refer the below image.
Add a view for index action method. Create new view in the Views->Document folder->Index.html
Add the navigation to agreement page
Pass the view model to view. I updated the code in index method in Documentcontroller. Refer the image.
Views->Document->Create.cshtml
@model Agreement.ViewModel.NewAgreementViewModel
@{
ViewBag.Title = "New Agreement";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="row">
<div class="col-12">
<div class="card border border-0 pt-1 pb-1 text-danger">
<h3>New Agreement </h3>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-12">
<div class="agreement pt-0 pb-3 pl-3 pr-3">
@using (Html.BeginForm("SaveAgreement", "Document", FormMethod.Post,
new { enctype = "multipart/form-data", role = "form" }))
{
<div class="row">
<div class="col-md-3 col-sm-3 col-lg-3 p-1">
<div class="card infobox">
<div class="card-header p-1 text-center">
<h4>Premises Details </h4>
</div>
<div class="card-body p-1">
<div class="form-group">
@Html.LabelFor(m => m.PremisesAddress1, new { @class = "control-label p-0 m-0" })
<span class="requiredfiled">* </span>
@Html.TextBoxFor(m => m.PremisesAddress1, new { @class = "form-control form-control-sm" })
@Html.ValidationMessageFor(m => m.PremisesAddress1, "", new { @class = "text-danger" })
</div>
<div class="form-group">
@Html.LabelFor(m => m.PremisesAddress2, new { @class = "control-label p-0 m-0" })
<span class="requiredfiled">* </span>
@Html.TextBoxFor(m => m.PremisesAddress2, new { @class = "form-control form-control-sm" })
@Html.ValidationMessageFor(m => m.PremisesAddress2, "", new { @class = "text-danger" })
</div>
<div class="form-group">
@Html.LabelFor(m => m.PremisesAddress3, new { @class = "control-label p-0 m-0" })
@Html.TextBoxFor(m => m.PremisesAddress3, new { @class = "form-control form-control-sm" })
@Html.ValidationMessageFor(m => m.PremisesAddress3, "", new { @class = "text-danger" })
</div>
<div class="form-group">
@Html.LabelFor(m => m.PremisesCity, new { @class = "control-label p-0 m-0" })
<span class="requiredfiled">* </span>
@Html.TextBoxFor(m => m.PremisesCity, new { @class = "form-control form-control-sm" })
@Html.ValidationMessageFor(m => m.PremisesCity, "", new { @class = "text-danger" })
</div>
<div class="form-group">
@Html.LabelFor(m => m.PremisesPincode, new { @class = "control-label p-0 m-0" })
<span class="requiredfiled">* </span>
@Html.TextBoxFor(m => m.PremisesPincode,
new { @class = "form-control form-control-sm", @maxlength = "6",
@onkeypress = "return isNumberKey(this,event)" })
@Html.ValidationMessageFor(m => m.PremisesPincode, "", new { @class = "text-danger" })
</div>
<div class="form-group">
@Html.LabelFor(m => m.PremisesDescription, new { @class = "control-label p-0 m-0" })
<span class="requiredfiled">* </span>
@Html.TextAreaFor(m => m.PremisesDescription,
new { @class = "form-control form-control-sm", @maxlength = "750", rows = "5" })
@Html.ValidationMessageFor(m => m.PremisesDescription, "", new { @class = "text-danger" })
</div>
<div class="form-group">
<input type="submit" value="Submit" class="btn btn-success" />
</div>
</div>
</div>
</div>
</div>
}
</div>
</div>
</div>
I have used the first approach which is "Strongly typed view model". To achieve this concept, we have to use strongly typed html control. All these controls should be placed within Html.BeginForm()
@using (Html.BeginForm("SaveAgreement", "Document", FormMethod.Post,
new { enctype = "multipart/form-data", role = "form" }))
{
Your html control goes here
<input type="submit" value="Submit" class="btn btn-success" />
}
Html.BeginForm() must have a "submit" button control. Then only the html control value will be passed to server post action method.
Some strongly typed html controls given below.
Model binding - All html input control value are submitted or passed to action method. That action method should be specified in Html.BeginForm().
When the user click the submit button, all html control values will be passed to the action method. The action method should be decorated with "HTTPPost" attribute. Here the action method is "SaveAgreement" and controller is "Document". This process is called as Model binding.
The following html code is the rendered content of the razor page(Create.cshtml). All the html input controls have the name and these name are the properties of viewmodel(AgreementViewModel.cs). If we use strongly typed view and strongly type html control, the view model property name will the name of html control. Look at the following html code.
<div class="row">
<div class="col-12">
<div class="card border border-0 pt-1 pb-1 text-danger">
<h3>New Agreement</h3>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-12">
<div class="agreement pt-0 pb-3 pl-3 pr-3">
<form action="/Document/SaveAgreement" enctype="multipart/form-data" method="post" role="form">
<div class="row">
<div class="col-md-3 col-sm-3 col-lg-3 p-1">
<div class="card infobox">
<div class="card-header p-1 text-center">
<h4>Premises Details</h4>
</div>
<div class="card-body p-1">
<div class="form-group">
<label class="control-label p-0 m-0" for="PremisesAddress1">Address1</label>
<span class="requiredfiled">*</span>
<input class="form-control form-control-sm" data-val="true"
data-val-length="The field Address1 must be a string with a maximum length of 250."
data-val-length-max="250" data-val-required="The Address1 field is required."
id="PremisesAddress1" name="PremisesAddress1" type="text" value="" />
<span class="field-validation-valid text-danger" data-valmsg-for="PremisesAddress1"
data-valmsg-replace="true"></span>
</div>
<div class="form-group">
<label class="control-label p-0 m-0" for="PremisesAddress2">Address2</label>
<span class="requiredfiled">*</span>
<input class="form-control form-control-sm" data-val="true"
data-val-length="The field Address2 must be a string with a maximum length of 250."
data-val-length-max="250"
data-val-required="The Address2 field is required."
id="PremisesAddress2"
name="PremisesAddress2" type="text" value="" />
<span class="field-validation-valid text-danger"
data-valmsg-for="PremisesAddress2"
data-valmsg-replace="true"></span>
</div>
<div class="form-group">
<label class="control-label p-0 m-0" for="PremisesAddress3">Address3</label>
<input class="form-control form-control-sm" data-val="true"
data-val-length="The field Address3 must be a string with a maximum length of 250." data-val-length-max="250"
id="PremisesAddress3" name="PremisesAddress3" type="text" value="" />
<span class="field-validation-valid text-danger" data-valmsg-for="PremisesAddress3"
data-valmsg-replace="true"></span>
</div>
<div class="form-group">
<label class="control-label p-0 m-0" for="PremisesCity">City</label>
<span class="requiredfiled">*</span>
<input class="form-control form-control-sm" data-val="true"
data-val-length="The field City must be a string with a maximum length of 250."
data-val-length-max="250" data-val-required="The City field is required." id="PremisesCity" name="PremisesCity" type="text" value="" />
<span class="field-validation-valid text-danger"
data-valmsg-for="PremisesCity" data-valmsg-replace="true"></span>
</div>
<div class="form-group">
<label class="control-label p-0 m-0" for="PremisesPincode">Pincode</label>
<span class="requiredfiled">*</span>
<input class="form-control form-control-sm" data-val="true"
data-val-length="The field Pincode must be a string with a maximum length of 6." data-val-length-max="6"
data-val-required="The Pincode field is required." id="PremisesPincode" maxlength="6" name="PremisesPincode"
onkeypress="return isNumberKey(this,event)" type="text" value="" />
<span class="field-validation-valid text-danger"
data-valmsg-for="PremisesPincode" data-valmsg-replace="true"></span>
</div>
<div class="form-group">
<label class="control-label p-0 m-0" for="PremisesDescription">Detail of the Premises</label>
<span class="requiredfiled">*</span>
<textarea class="form-control form-control-sm" cols="20" data-val="true"
data-val-length="The field Detail of the Premises must be a string with a maximum length of 1000."
data-val-length-max="1000" data-val-required="The Detail of the Premises field is required."
id="PremisesDescription" maxlength="750" name="PremisesDescription" rows="2">
</textarea>
<span class="field-validation-valid text-danger" data-valmsg-for="PremisesDescription"
data-valmsg-replace="true"></span>
</div>
<div class="form-group">
<input type="submit" value="Submit" class="btn btn-success" />
</div>
</div>
</div>
</div>
</div>
</form> </div>
</div>
</div>
Some additional attribute are available with html control. I will explain later.The html control name is playing main role for model binding process. But Id value are used in script libray such Javascript, jQuery.
The following image explain how the view model property rendered as a html controls.
Data validation refers to the process of ensuring the accuracy and quality of data. The validation is a condition and the data should satisfy condition.
If the data is not satisfy the condition, then the data become invalid and should not proces further with the data
The application developer should not trust the end user input data. They may enter any data, any order, any format. The software developer have the responsibility to write the code to validate the input data and provide user friendly message to the end user if it is invalid data. Based on the validation message, the end user may correct the data and re-submit the data. Even if there is single invalid data, should not allow the end user to go further.
Usually, the developer has to write code to validate each and every input field value. But, now days so many script libraries are available, we can use them. In MVC, the data annotations has been used to implement the validation with minimum effort. If you look at above html code, you can find some validation attribute with html control. This is the magic of data annotations.
Some sample data validation attribute for html input controls
.Net MVC support to use build in method called "ModelState.IsValid" to validate the model.
[HttpPost]
public ActionResult SaveAgreement(NewAgreementViewModel viewModel)
{
if(!ModelState.IsValid)
{
return View("Create", viewModel);
}
return View("Create",viewModel);
}
Add a class in "Agreement.Domain" project. Refer the below image.
When the end user using the application, if any error occur, the application will be stopped and user cannot continue further. The invalid data can cause the error or some unexpected behavious may cause the error such as server error, database connection error or network failure. These all are unexpected behaviour. If any unexpected error occur, we have to handle the error and provide the user friendly message to the end user. We have to use exception handling mechanism to handle this issue and have to log the error information for further or future analysis. The developer should not display the actual error message in the front application. If the developer display the actual exception in the front end application, the hacker may misuse the application or break the application.
So far, I have explained, how to develop a module to save the information. Next, I going to add some additional table and migrate the database. The following image shows complete design view.