Professional Documents
Culture Documents
Part 0 Introduction:
Our main goal is to develop a MVC website for a hypermarket using .NET framework and
following this architecture:
DataBase
Front-Office
Back-Office
MyFinance.Web
Reference
MyFinance.Data
MyFinance.Domainn
W
(MyF
BLL : Busi
(MyFinanc
DAL : Da
(MyFinan
5. Click OK
We've made the navigation properties virtual so that we get lazy loading.
DateTime? Type is the nullable DateTime
We used ICollection interface so we can use later any collection implementation.
Web.config
8. Click Add
9. Explore the generated Controller and Views
Step 5 : Run and enjoy
Follow these steps:
1. Right click the MyFinance.Web project
2. Click Set as start-up project
Step 2 : Assuming that we are using a production environment and we have important
data. Then we are not allowed to lose this data. In this case the initialisation
strategy doesn't seem to be a good choice. So lets try something else,
Migration !!!! Lets do it.
1. The first step: we have to enable the Migration: Open the Package
Manager Console the choose the project MyFinance.Data which
contains the class Context. Then execute this command EnableMigrations
Entity Framework Code First generate a new folder Migration which contains
two classes xxx_InitialCreate and Configuration.
-The first class contains an Up () method that contains instructions to create the
table with its original definition, and another method Down () to delete the table.
-The second class define the behavior of the migration for DbContext used. This is
where you can specify the data to insert, enter the providers of other databases
2. The second step: we will change the name of the property public string
Image { get; set; } to public string ImageName { get; set; }.
3. Execute the command Add-Migration ModifyNameImage in the
Package Manager Console.
4. The Add-migration command checks for changes since your last
migration and scaffold a new migration with any changes found. We can
give a name for our migration, in this case, we call migration
"ModifyNameImage".
To create a new Complex Type we have to follow those rules otherwise we have to
configure a complex type using either the data annotations or the fluent API.
Step 2 : Lets update Chemical entity with the complex type as the following :
public class Chemical : Product
{
public string LabName { get; set; }
public Address LabAddress { get; set; }
}
Step 2 : Now , we will add different data annotations to configure those entities.
[DataType(DataType.Currency)]
public double Price { get; set; }
[Range(0, int.MaxValue)]
public int Quantity { get; set; }
[DataType(DataType.ImageUrl),Display(Name = "Image")]
public string ImageName { get; set; }
[Display(Name = "Production Date")]
[DataType(DataType.DateTime)]
public DateTime DateProd { get; set; }
//foreign Key properties
public int? CategoryId { get; set; }
//navigation properties
[ForeignKey("CategoryId ")]
//useless in this case
public virtual Category Category { get; set; }
public virtual ICollection<Provider> Providers { get; set; }
}
MaxLength is used for the Entity Framework to decide how large to make a string
value field when it creates the database.
StringLength is a data annotation that will be used for validation of user input.
DataType : is used to specify a specific type : email, currency, card number
Display is used to change the displayed name of the property
Range is used to limit valid inputs between min and max values.
Foreignkey : To configure the foreign key
The Many to many part configure the association between the Product class and
The Provider class
Step 4 :Finally we configure the complex type Address by creating this class:
public class AddressConfiguration : ComplexTypeConfiguration<Address>
{
public AddressConfiguration()
{
Property(p => p.City).IsRequired();
Property(p => p.StreetAddress).HasMaxLength(50)
.IsOptional();
}
}
Step 6 : Update the database by migration and explore it to see what the
configurations have done.
Add a class Disposable which inherit from the IDisposable interface in the
Infrastructure folder.
public class Disposable : IDisposable
{
// Track whether Dispose has been called.
private bool isDisposed;
// Use C# destructor syntax for finalization code.
// This destructor will run only if the Dispose method
// does not get called.
// It gives your base class the opportunity to finalize.
// Do not provide destructors in types derived from this class.
~Disposable()
{
// Do not re-create Dispose clean-up code here.
// Calling Dispose(false) is optimal in terms of
// readability and maintainability.
Dispose(false);
}
public void Dispose()
{
Dispose(true);
-This class implement the design pattern Factory, in fact before talking about
this design pattern, lets see two great principals that stands on the base of many
design and architecture decisions.
-Then we will add an RepositoryBase class. In the first hand, we create this
abstract class is a generic class which contain generics CRUD methods. In the
second hand , well add the different repositories which inherit from this base
Repository.
-As we see in this class, we pass a DatabaseFactory object through the
constructor and we create a generic Set since this Set will be used by the
different entities.
-After getting the Context object created by the DatabaseFactory we add some
generics methods.
-Note that in somes methods like public virtual void
Delete(Expression<Func<T, bool>> where)
}
public virtual T GetById(string id)
{
return dbset.Find(id);
}
public virtual IEnumerable<T> GetAll()
{
return dbset.ToList();
}
public virtual IEnumerable<T> GetMany(Expression<Func<T, bool>> where)
{
return dbset.Where(where).ToList();
}
public T Get(Expression<Func<T, bool>> where)
{
return dbset.Where(where).FirstOrDefault<T>();
}
}
Step 10 :-Now we will see the last design pattern in our project The Unit Of
Work.
-The idea is that we can use the Unit of Work to group a set of related operations
the Unit of Work keeps track of the changes that we are interested in until we
are ready to save them to the database.
-The pattern Unit Of Work consists in making one or more transactions database
committed or rolled back together.
-The pattern "Unit of work" is used to:
return Products;
}
public IEnumerable<Chemical> GetChemicals()
{
var Chemicals = utOfWork.ProductRepository.GetAll().OfType<Chemical>();
return Chemicals;
}
public Biological GetBiologicol(int id)
{
var Biological = utOfWork.ProductRepository.GetById(id) as Biological;
return Biological;
}
public Chemical GetChemical(int id)
{
var Chemical = utOfWork.ProductRepository.GetById(id) as Chemical;
return Chemical;
}
public void CreateProduct(Product p)
{
utOfWork.ProductRepository.Add(p);
utOfWork.Commit();
}
public Product GetProduct(int id)
{
var Product = utOfWork.ProductRepository.GetById(id);
return Product;
}
public void UpdateProduct(Product p)
{
utOfWork.ProductRepository.Update(p);
utOfWork.Commit();
}
public IEnumerable<Product> GetProductsByCategory(string categoryName)
{
return utOfWork.ProductRepository.GetMany(x => x.Category.Name ==
categoryName);
}
public void Dispose()
{
utOfWork.Dispose();
}
}
3. Explore the generated view under the Products folder, and change the
Html.BeginForm() method to the folowing
Html.BeginForm("CreateBiological", "Products", FormMethod.Post, new { enctype =
"multipart/form-data" })
Now, you have a multi-part form and so you can upload files with your data.
4. Change the editor for the image name from a simple text box to a file
upload input
@Html.Editor("file", new { htmlAttributes = new { @class = "form-control", type = "file" } })
6. Add a checkbox under the drop down list to check if the inserted product is
a new One !
<div class="form-group">
@Html.Label("New ?", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.CheckBox("isNew", new { htmlAttributes = new { @class = "form-control" } })
</div>
</div>
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
else
{
return View(p);
}
3.
@model MyFinance.Domain.Entities.Biological
@{
ViewBag.Title = "ValidateBiological";
bool? isNew = Convert.ToBoolean(TempData["isNew"]);
}
<h2>Validate Biological</h2>
<div>
@if (isNew == true)
{
<h1>New Biological Product !!</h1>
}
else
{
<h4>Biological Product !!</h4>
}
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Description)
</dt>
<dd>
@Html.DisplayFor(model => model.Description)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Name)
</dt>
<dd>
@Html.DisplayFor(model => model.Name)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Price)
</dt>
<dd>
@Html.DisplayFor(model => model.Price)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Quantity)
</dt>
<dd>
@Html.DisplayFor(model => model.Quantity)
</dd>
<dt>
@Html.DisplayNameFor(model => model.ImageName)
</dt>
<dd>
@Html.DisplayFor(model => model.ImageName)
</dd>
<dt>
@Html.DisplayNameFor(model => model.DateProd)
</dt>
<dd>
@Html.DisplayFor(model => model.DateProd)
</dd>
<dt>
@Html.DisplayNameFor(model => model.CategoryId)
</dt>
<dd>
@Html.DisplayFor(model => model.CategoryId)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Herbs)
</dt>
<dd>
@Html.DisplayFor(model => model.Herbs)
</dd>
</dl>
</div>
<p>
@Html.ActionLink("Confirmation", "ValidateBiological", new { insertion = true }) |
@Html.ActionLink("Cancel", "Index")
</p>
Step 2 -
Right-click inside the Index action method and select Add View. This will bring up
the Add View dialog.
1.
Review the code created. The generated list of fields will be part of the following
HTML table that Scaffolding is using for displaying tabular data.
2.
Replace the code under the title <h2>Index</h2> by the next code
@model IEnumerable<MyFinance.Domain.Entities.Product>
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
@using (Html.BeginForm())
{
<table>
<tr>
<td>
<div>
Search by category: @Html.TextBox("categoryName")
</div>
</td>
<td>
<input type="submit" value="Search" id="submit" />
</td>
<td>
@ViewBag.Message
</td>
</tr>
</table>
}
<div id="divExpenseList">
<p>
@Html.ActionLink("Create New", "CreateBiological")
</p>
</div>
-We use
the Razor
View
Engine
and
HTML
helpers
to
generate
HTM
tags. For
example
the
@Html.Te
xtBox("ca
tegoryNam
e ")
Helper
will
generate
the next
tag:
<input
id='categ
oryName'
name='categoryName' />
-Note: To understand Razor, you can view this blog
http://weblogs.asp.net/scottgu/archive/2010/07/02/introducing-razor.aspx.
And this blog for HTML Helper
http://www.mikesdotnetting.com/Article/184/HTML-Helpers-For-Forms-In-RazorWeb-Pages
-Back to the code this view, the Html.BeginForm() Helper will generate a form
which will send the data by default to the current action Index located in the
ProductController.
-In fact when a form send data to the controller, we need another version of the
current action. In our case the Index action. To make the difference between the
two actions named Index, the second version which retrieve data from the view
will be decorated by the attribute [HttpPost], the first action will use by default
the Get mode.
[HttpPost]
-Before
implementing this action, we will continue with our View. The next Helper
@Html.ActionLink("Create New", "CreateBiological") will generate an
Hyperlink.It should redirect to The CreateBiological action.
-Before moving to the controller, we notice that this view lacks the display part,
where we display the list of products retrieved from the database.
- Step 4 Working with Partial View
- A partial view is used when you have some view component that is used in
more than one place, or is better separated in to a separate file (for readability,
for example).
-In our case, instead of displaying the list of products in this view, we will create a
partial view where we will display the description, the price and the image of a
product. Then,in the Index view we will display this partial view as well as we
have products.
-Lets add our partial view, Right click on the Product folder located in Views
folder, then Add View:
-This partial view is strongly typed. First we create a string field where we store
the hole path of the image. Then we display the imge using
@Url.Content(path) Helper which converts a virtual (relative) path to an
application absolute path
-The Model object contain the Product object passed from the Controller.
-The >@Html.ActionLink("Details", "Details",new { id = Model.ProductId }) will
generate an HyperLink which redirect to the Details action. This tag will send
the value of the ProductId of the current product object to the Details action.
Lets adding a custom Helper.
- Step 5 Adding an HTML Helper
-
The Desription properties can be long. In this step you will learn how to
add a custom HTML helper to truncate that text.
In this task, you will add a new method Truncate to the HTML object
exposed within ASP.NET MVC Views. To do this, you will implement an
extension method to the built-in System.Web.Mvc.HtmlHelper class
provided by ASP.NET MVC.
Add the following code below the @model directive to define
the Truncate helper method.
<p>@Truncate(Model.Description, 25)</p>
-This action
retrieve a
string which
present the
category
chosen by the
user from the
view. Then
retrieve the
list of
products by
category, and
-At a high level, the goal of Dependency Injection is that a client class (e.g. the golfer) needs
something that satisfies an interface (e.g. IClub). It doesn't care what the concrete type is
(e.g. WoodClub, IronClub, WedgeClub or PutterClub), it wants someone else to handle that
(e.g. a goodcaddy). The Dependency Resolver in ASP.NET MVC can allow you to register
your dependency logic somewhere else (e.g. a container or a bag of clubs).
What is DI Container
A DI Container is a framework to create dependencies and inject them automatically
when required. It automatically creates objects based on request and inject them when
required. DI Container helps us to manage dependencies with in the application in a simple
and easy way.
We can also manage an application dependencies without a DI Container, but it will be like
as POOR MANS DI and we have to do more work, to make it configured and
manageable.