You are on page 1of 43

ASP.

NET MVC Documents Sample

Eric Goedhart, 6 May 2014 CPOL


4.81 (31 votes)
Rate this:
vote 1vote 2vote 3vote 4vote 5
Building a ASP.Net datadriven website

Introduction
This article is about the creating of a basic ASP.NET MVC 4 Web Application that has the task
of keeping track of incoming documents. For the creation of the project the Code First
approach is used so we write the needed Classes and from them create the database. After the
creation of the Database we create the Controllers and Views we need and wire them up to get a
working Web Application were we can Create,Read,Edit, and Delete records.
This article consists out of 5 parts:
1. Creating the basic ASP.NET MVC Web Application
2. Creating the Classes
3. Creating the Database
4. Creating the Controllers and Views

Background
This article is not going to talk about the MVC Model itself or how the Controllers work and so
on because a lot is written about that already in other articles. The main goal I have with this
article is to show someone who starts with programming to go from nothing to a fully working
Web Application with Dynamic data. With Dynamic data I mean that no static lists will be in the
HTML code, all data in the lists will come from the database and can be changed if needed.

When this sample is finished it's far from ready because I didn't pay attention to the validation of
the data a user enters and so on so it' a rough working model that's ready for the next phase.
That next phase will be changing the look and feel and adding functionality. At the moment I am
writing the next addition to the article that I will publish as a separate article that builds further
on the code. At the end it will be similar to the version I use myself at home to keep track of the
incoming standard mail that is scanned by a standard document scanner and is uploaded to this
webite. The Document_uri string in the Document.cs Class in this article is used to link the
scanned document and wen clicked present that .PDF in the browser. The end result will be a
handy application were documents otherwise is maps are quickly found when needed.

Using the code


I have build this sample in Visual Studio 2012 Professional and after that tested in Visual Studio
2013 Ultimate 90 day's trial version to see if it works as it does so you can use that version also.
Important: Make sure that EntityFramework is installed. To find out click on the created project
in the Solution Explorer and go to Manage NuGet Packages... en select the All View in the next
Screen, if it's not in the list go to the Online option at the left and you get a list of available
packages, select EntityFramework and Click on Install, a reference will be added in your project.
Download Code (MvcDocuments Sample)
Click on the MvcDocuments Sample in OneDrive and select download:

1.Creating the basic ASP.NET MVC Web Application


The first step in this project is the creation of the skeleton we are going to use and we start with
the New Project option from the Visual Studio 2012 menu.

We get the following screen were we select the ASP.NET MVC 4 Web Application in Visual
C# ,to get this option select the Web option as shown below ,give the application
MVCDocuments as name and then Click on the OK button.

In the next screen we select the Internet Application option and we make sure that as View
engine: Razor is selected and again we click on the OK button.

The project skeleton is created and we go to Solution Explorer under the VIEW menu option.

In the Solution Explorer we see the MvcDocuments project and when we open the Models
folder. We see that one Model is already there, the AccountModels.cs file that takes care of the
Registering and Login process of the Web Application.

At this moment we are not interested in that AccountModels.cs file, first we start Debugging the
Web application to see if it works.

If everything is OK we will get the following screen in the Web Browser , as you can see we
have a Register and a Login Button at the right top of the screen and a Home , About and Contact
button just below them.

Let's test the Register option first and create a User name and Password.

If everything is OK you see that Hello and your User name has replaced the Register Button and
the Login Button is replaced by a Log off option.
The just created application works but under the hood happened something else, a database with
the name: aspnet-MvcDocuments-20140404125332.mdf is created (the digits are the year and
time of creation), there is also a similar named Log file. You can find both files in your projects
APP_Data folder when you Right Click on that and Select Open Folder in File Explorer
Note: You can view the database also with your Server Explorer that you can find under the
VIEW menu option.

2.Creating the Classes


We have created the basic skeleton for our application. The next step is writing the Classes we
need. We want the Classes in the Models folder so go to the Solution we Right Click on that
folder and select the Menu Option Add and select Class from the options. Make sure you select
the Visual C# Class and name it : Company.cs
I now could give you a lot of screens but instead of that I give you the code for the Classes you
have to create. All Classes together will later on create the Context of the Documents part of this
sample application.
All the Classes belong in the Models folder. Notice that sometimes - while writing the code
-referenced Classes do not exist at that moment so a red wave will be visible under those parts in
the code, just ignore that for the moment.

1.The Company.cs Class:

Hide Shrink
using
using
using
using

Copy Code

System;
System.Collections.Generic;
System.Linq;
System.Web;

namespace MvcDocuments.Models
{
public class Company
{
//Identifier
public int CompanyId { get; set; }
//Company
public string Company_name { get; set; }
public string Address { get; set; }
public string Postal_Code { get; set; }
public string City { get; set; }
// State
public int StateId { get; set; }
public virtual State State { get; set; }
//Country
public int CountryId { get; set; }
public virtual Country Country { get; set; }
//Communication
public string Phone { get; set; }
public string Email { get; set; }
public string Website_Uri { get; set; }
//List Contacts
public virtual List<Contact> Contacts { get; set; }
//List Documents
public virtual List<Document> Documents { get; set; }
}
}

2.The Contact.cs Class:


Hide Shrink
using
using
using
using

Copy Code

System;
System.Collections.Generic;
System.Linq;
System.Web;

namespace MvcDocuments.Models
{
public class Contact
{
//Identifier
public int ContactId { get; set; }
//Company
public int CompanyId { get; set; }
public virtual Company Company { get; set; }
//Function
public int FunctionId { get; set; }
public virtual Function Function { get; set; }
//Title

public int TitleId { get; set; }


public virtual Title Title { get; set; }
//Contact
public string Surname { get; set; }
public string Last_name { get; set; }
//Communication
public string Email_address { get; set; }
public string Phone { get; set; }
public string Cellphone { get; set; }

3.The Costs_group.cs Class:


Hide Copy Code
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
System.Web;

namespace MvcDocuments.Models
{
public class Costs_group
{
//Identifier
public int Costs_groupId { get; set; }
//Costs group
public string Cost_group_name { get; set; }
}
}

4.The Country.cs Class:


Hide Copy Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MvcDocuments.Models
{
public class Country
{
//Identifier
public int CountryId { get; set; }
//Country
public string Country_name { get; set; }
}
}

5.The Document.cs Class:


Hide Shrink

Copy Code

using
using
using
using

System;
System.Collections.Generic;
System.Linq;
System.Web;

namespace MvcDocuments.Models
{
public class Document
{
//Identifier
public int DocumentId { get; set; }
//Document date
public DateTime Document_date { get; set; }
//Company
public int CompanyId { get; set; }
public virtual Company Company { get; set; }
//Mail category
public int Mail_categoryID { get; set; }
public virtual Mail_category Mail_category { get; set; }
//Costs group
public int Costs_groupId { get; set; }
public virtual Costs_group Costs_group { get; set; }
//Payment status
public int Payment_statusId { get; set; }
public virtual Payment_status Payment_status { get; set; }
//Bill
public string Reference { get; set; }
//Note
public string Note { get; set; }
//Financial
public double AmoutExVat { get; set; }
public double Vat { get; set; }
public double Amount { get; set; }
//.PDF Link
public string Document_uri { get; set; }
}
}

6.The Function.cs Class:


Hide Copy Code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MvcDocuments.Models
{
public class Function
{
//Identifier
public int FunctionId { get; set; }
//Function
public string Function_name { get; set; }
}
}

7.The Mail_category.cs Class:


Hide Copy Code
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
System.Web;

namespace MvcDocuments.Models
{
public class Mail_category
{
//Identifier
public int Mail_categoryId { get; set; }
//Mail category
public string Mail_category_name { get; set; }
}
}

8.The Payment_status.cs Class:


Hide Copy Code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MvcDocuments.Models
{
public class Payment_status
{
//Identifier
public int Payment_statusId { get; set; }
//Payment status
public string Payment_status_name { get; set; }
}
}

9.The State.cs Class:


Hide Copy Code
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
System.Web;

namespace MvcDocuments.Models
{
public class State
{
//Identifier
public int StateId { get; set; }
//State
public string State_name { get; set; }
}

10.The Title.cs Class:


Hide Copy Code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MvcDocuments.Models
{
public class Title
{
//Identifier
public int TitleId { get; set; }
//Title
public string Title_name { get; set; }
}
}

11.The MvcDocumentsContext.cs Class:


All the Above created Classes will form together the so called Context of our application. There
is one more Class we need to create in the Models folder and that is the Context Class. We call
this Class: MvcDocumentsContext.cs , the code for that Class is:
Hide Copy Code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
namespace MvcDocuments.Models
{
public class MvcDocumentsContext : DbContext
{
public DbSet<Company> Companies { get; set; }
public DbSet<Contact> Contacts { get; set; }
public DbSet<Costs_group> Costs_groups { get; set; }
public DbSet<Country> Countries { get; set; }
public DbSet<Document> Documents { get; set; }
public DbSet<Function> Functions { get; set; }
public DbSet<Mail_category> Mail_categories { get; set; }
public DbSet<Payment_status> Payment_statusses { get; set; }
public DbSet<State> States { get; set; }
public DbSet<Title> Titles { get; set; }
}
}

As you can see one using is added below using System.Web; We have added the using
System.Data.Entity to it

Notice also the following line in the code above:


public class MvcDocumentsContext : DbContext
The: DbContext is new also.
OK I think we are done regarding the creation of the Classes and the needed Context so we can
close the Models folder and move on to our next step. Our next step will be the creation of the
Database based on our MvcDocumentsContext.cs and the Classes we just wrote.

3.Creating the Database


In this part we are going to create the Database based on the Classes we have written in the
previous part. The first thing we are going to do is adding a line in the Webconfig file. You can
find that file at the bottom in the Solution Explorer. Open this file and look for this part where it
say's: <connectionString>...</connectionStrings>
Hide Copy Code
<connectionStrings>
<add name="DefaultConnection" connectionString="Data
Source=(LocalDb)\v11.0;Initial Catalog=aspnet-MvcDocuments20140405094433;Integrated Security=SSPI;AttachDBFilename=|
DataDirectory|\aspnet-MvcDocuments-20140405094433.mdf"
providerName="System.Data.SqlClient" />
</connectionStrings>

Please add the following line of code:


Hide Copy Code

<add name="MvcDocumentsContext" connectionString="Data


Source=(LocalDb)\v11.0;Initial Catalog=aspnet-MyDocuments;Integrated
Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-MyDocuments.mdf"
providerName="System.Data.SqlClient" />

When done your code should look like this:


Hide Copy Code

<connectionStrings>
<add name="DefaultConnection" connectionString="Data
Source=(LocalDb)\v11.0;Initial Catalog=aspnet-MvcDocuments20140405094433;Integrated Security=SSPI;AttachDBFilename=|
DataDirectory|\aspnet-MvcDocuments-20140405094433.mdf"
providerName="System.Data.SqlClient" />
<add name="MvcDocumentsContext" connectionString="Data
Source=(LocalDb)\v11.0;Initial Catalog=aspnet-MyDocuments;Integrated
Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-MyDocuments.mdf"
providerName="System.Data.SqlClient" />
</connectionStrings>

Be aware that the digits in the first line can vary and don't replace your own code with the code
above since your Database won't work in that case). When you are done it's a good idea to
rebuild the solution (BUILD menu and Rebuild Solution option).
The next step is creating the Database , we have added a Connection String to work with and we
are going to use the Package Manager Console Tool in Visual Studio. You can find this under the
TOOLS menu, look for the NuGet Package Manager and select that and click on the Package
Manager Console to open it.
Hide Copy Code
Each package is licensed to you by its owner. Microsoft is not responsible
for, nor does it grant any licenses to, third-party packages. Some packages
may include dependencies which are governed by additional licenses. Follow the
package source (feed) URL to determine any dependencies.
Package Manager Console Host Version 2.8.50126.400
Type 'get-help NuGet' to see all available NuGet commands.
PM>

You see some license information and PM> , after that you type the following line:
PM> Enable-Migrations -contexttypename MvcDocuments.Models.MvcDocumentsContext

And you hit the Enter key on you keyboard. If everything is OK you get the following text in the
Console:
Hide Copy Code

PM> Enable-Migrations -contexttypename MvcDocuments.Models.MvcDocumentsContext


Checking if the context targets an existing database...
Code First Migrations enabled for project MvcDocuments.

But you wont notice that because a new folder is created in your project with the name
Migrations and a File called Configuration.cs also, that's the screen you are looking at:
In the following part of the Configuration.cs code the AutomaticMigrationsEnabled is default
set to = false; , you have to set it to = true; as shown below:
Hide Copy Code
namespace
{
using
using
using
using

MvcDocuments.Migrations
System;
System.Data.Entity;
System.Data.Entity.Migrations;
System.Linq;

internal sealed class Configuration :


DbMigrationsConfiguration<MvcDocuments.Models.MvcDocumentsContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(MvcDocuments.Models.MvcDocumentsContext
context)
{

version.

//

This method will be called after migrating to the latest

Now Rebuild your Solution (Menu option BUILD/Rebuild Solution) and go to the Package
Manager Console again and type:
PM> Add-Migration DocumentsDatabaseCreation

After hitting your Enter key a new Migrations file will be created in your Migrations folder
(Digits will be different). Again you won't notice that because the configuration file just created
will be visible but go back to the Console and type:
PM> Update-Database

After hitting the Enter key again the Database will be created:
Hide Copy Code

PM> Update-Database
Specify the '-Verbose' flag to view the SQL statements being applied to the
target database.
Applying code-based migrations: [201404050752573_DocumentsDatabaseCreation].
Applying code-based migration: 201404050752573_DocumentsDatabaseCreation.
Running Seed method.
PM>

To see if that really happened have a look at your Server Explorer under the VIEW menu in
Visual Studio:

As you can see the Database is created and that was the goal of this Part next we are going to
create the Controllers and Views and wire things up so we get a working application.

4.Creating the Controllers and Views


In the previous parts we created the MVCDocuments solution skeleton, wrote the Classes and
created the Database. In this part we are going to create the Controllers and Views for this
application and we are going to wire things up so we get a working Application.
We start with the Controllers folder (two files are already there) and we Right Click on that
folder and Select the Add Controller option:

We are going to Add the Controllers for all the Classes we have created so let's start with the
Company.cs Class we have created and name the Controller as shown above:
CompanyController.
Make sure that as the Model class: Company(MvcDocuments.Models) is selected and that as the
Data context class: MvcDocumentsContext (MvcDocuments.Models) is selected as shown in
the picture above.
Make also sure that under Scaffolding options:Mvc controller with read/write actions
and views, using Entity Framework is selected!
As I said you need to create a Controller per Class , so after you click on Add for the creation of
the Company Controller you do the same for all of them except for the
MvcDocumentsContext.cs Class.

When you are done with creating the Controllers you will have noticed that automatically Views
were created during the creation of the Controllers as you can see in the image above just after
the creation of the Company Controller.
If everything went well almost all needed Views were created and our next step will be wiring
them up so views will be visible and functioning in our Web Browser when we Debug our
application.
Create a new Controller and call this one: ListController , under Scaffolding options select the
Empty MVC controller and click on the Add button.

You will see the following code on your screen:


Hide Copy Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MvcDocuments.Controllers
{
public class ListController : Controller
{
//
// GET: /List/
public ActionResult Index()
{
return View();
}
}
}

This controller Class will redirect requests for the List page, Put your cursor at the right side of
the return View(); so next to the Comma and Right Click there and select: The Add View...
menu option.

In the screen that follows just make sure the default Index is set as the name and leave the res as
it is.

A new View folder with the name: List will be created and inside that folder the Index.cshtml file
is created and if everything is OK you are presented with it's contents on your screen. We are
going to make some changes to this part so I looks like this:
Hide Copy Code
@{

ViewBag.Title = "Lists";

}
<h2>Lists</h2>

This will present links to the named pages when the Lists Index.cshtml page is requested.
The next thing we are going to do is we are going to find the Shared folder in our Views folder
and open the _Layout.cshtml file, and we are going to look for the following part in that:
Hide Copy Code

<ul id="menu">
<li>@Html.ActionLink("Home", "Index", "Home")</li>

The above shown part is shown as Navigation Buttons in the Web Page and you have seen them
with the first Debugging session in the beginning.

We are going to change the above shown .cshtml code to this:


Hide Copy Code
<ul id="menu">
<li>@Html.ActionLink("Home", "Index", "Home")</li>

As you can see only the Home link is kept and we added links to our Contact, Company
Document and Link pages.
As you can see the Index page will be requested when clicked on the link. Let's see what we
have when we hit the F5 button, if everything is OK the application will run and the Web Page is
presented as seen below:

As you can see the Contact, Companies, Documents and List buttons are there.
It's important to understand that the content from for example a new Company you add to the
Database partly depends on your Lists, have a look at the screen below:

As you can see (or test yourself on the running website) there's nothing in the State or Country
list because there no data added yet to either one of them. So first we have to fill in the lists so
click on the List button.

Let's enter some data per List so click on the first link and enter a few cost names you can think
of such as rent, energy, health care, insurance , add at least a few countries to the list of
Countries, for the Function add for example Manager to it and Consultant, for the Mail Category
add Bill and Letter and for Payment Status Add Due and Payed, and a few states to the state list
and as last add for the Title list Mr. and Mrs. to it.
OK we have entered some data into the Lists so this data should be visible when we go to the
Companies and click on the create link.

As you can see the Data we entered is there. As you will understand you first must create a
Company before that company will be selectable when you want to add a new document to the
database.
Try the other screens a also so create a new Contact, create a Bill and play around with it.

Points of Interest
The created MvcDocuments sample will in the second part:
http://www.codeproject.com/Articles/767635/ASP-NET-MVC-Documents-sample-Part
be extended with taking care of the uploading from .Pdf scans of the Documents and the on
screen presentation of them when selected and some other changes regarding the presentation of
the data. In that part also search functionality will be added in the Controllers code and
implemented in the screens.
I enjoyed creating it for this part and I hope readers will follow the steps above to create this web
application. If any questions please ask.

ASP.NET MVC Documents sample Part 2

Eric Goedhart, 1 May 2014 CPOL


4.80 (14 votes)
Rate this:
vote 1vote 2vote 3vote 4vote 5
Part two of the ASP.NET MVC Documents Sample

Introduction
This article that is the second part of the ASP.NET MVC Documents Sample, if you didn't read
that please first have a look at :
http://www.codeproject.com/Articles/755459/ASP-NET-MVC-Documents-Sample
In this part we are going to extend the previous build version. Basically what we want is to show
the data as we want.

Above is a screen shot of what we want for our documents view.


There will be a lot of document and company records in the database after using the application
for a while and we don't want them all on one page displayed so we have to add Paging. It's also
handy that we can search for a specific company instead of going true all the companies by hand
to find the company we are looking for so we have to add Search functionality to the application.
When we enter a new Company to our database and we go back to the list we don't get the
companies in alphabetical order so we have to write some code to make it Sort on alphabetical
order.Then there is also the fact that we don't want anyone to see our documents so we have to
make sure that only those who are logged in can view them. We have to build that in also. And
we want to upload the scans we make from the real documents that we get in our mail and make
them available as .PDF in our application. So we need to create an upload for that and create a
link to view these documents in the browser.
To sum it up:

1. Create paging
2. Add search functionality
3. Add Alphabetical Sorting
4. Make it private

5. Create an upload.
6. Validation
Thats what we are going to do in this part.

Background
This article is not going to talk about the MVC Model itself or how the Controllers work and so
on because a lot is written about that already in other articles. The main goal I have with this
article is to show someone who starts with programming to go from nothing to a fully working
Web Application with Dynamic data. With Dynamic data I mean that no static lists will be in the
HTML code, all data in the lists will come from the database and can be changed if needed.

Using the code


I have build this sample in Visual Studio 2012 Professional and after that tested in Visual Studio
2013 Ultimate 90 day's trial version to see if it works as it does so you can use that version also.
Important: Make sure that EntityFramework is installed. To find out click on the created project
in the Solution Explorer and go to Manage NuGet Packages... en select the All View in the next
Screen, if it's not in the list go to the Online option at the left and you get a list of available
packages, select EntityFramework and Click on Install, a reference will be added in your project.
You can download the Project from my OneDrive:
https://onedrive.live.com/redir?resid=CDF4A34C128AE7C4%213254
Click on the MvcDocuments Sample in OneDrive and select download:

1. Create Paging
The first thing we are going to do is Add a reference to the Application, to do that go to the
TOOLS menu in Visual Studio and Select NuGet Package Manager and in that the Option
Manage NuGet Packages for Solution... as shown below in the Image:

You will get the following screen:

Select the Online tab at the left and type: PagedList in the top corner search box at the right, you
will get the above shown result and if you Click on Install this PagedList will be added to the
solution.Have a look with the Solution Explorer and expand The Reference Folder you will see
that a reference to the PagedList Library is added as shown below:

Now we can use PagedList and add paging to our application. To do so we are going to change
some code , lets start with implementing paging in our Document part of the application.
As you remember from the first part of the MVCDocuments Sample we have created
Controllers, we didn't touch these controllers at all but now we are going to change a part of the
DocumentController.cs code. Please go to the Solution Explorer, Expand the Controllers folder
and find the DocumentController.cs file and open it.
We are going to Add a using reference to the Library file PagedList we just have added in the
previous part and make use if the PagedList Library.
First add the using PagedList; to the using part of this Class as shown below as //Added:
Hide Copy Code
using
using
using
using
using
using
using
using
using

System;
System.Collections.Generic;
System.Data;
System.Data.Entity;
System.Linq;
System.Web;
System.Web.Mvc;
PagedList; //Added
MvcDocuments.Models;

Then go to the following part of the Code:


Hide Copy Code

public ActionResult Index()


{
var documents = db.Documents.Include(d => d.Company).Include

(d => d.Mail_category).Include(d => d.Costs_group).Include(d =>


d.Payment_status);
return View(documents.ToList());
}

We are going to change this code to this:


Hide Copy Code

public ViewResult Index(int? page)


{
var documents = db.Documents.Include(d => d.Company).Include
(d => d.Mail_category).Include(d => d.Costs_group).Include
(d => d.Payment_status).OrderByDescending(d => d.Document_date);
//Pager
int pageSize = 2;
int pageNumber = (page ?? 1);
//Return content
return View(documents.ToPagedList(pageNumber, pageSize));
}

As you can see a lot has changed, this method has changed from a ActionResult into a
ViewResult and the sort order is added with:
.OrderByDescending(d => d.Document_date);
The code for the pager is Added. As you can see the pageSize is set to 2 so two records will be
shown per page but you can change that (I have set the value to 2 for testing purposes). Notice
that the return View is changed to: Documents.ToPagedList(...) so a Paged List will be returned.
When you have made these changes to the: DocumentController.cs files code go to the Solution
Explorer and Expand the Views folder and go to the Index.cshtml file and open that file.

On top of the code of this: Index.cshtml page you see this line:

Hide Copy Code


@model IEnumerable<MvcDocuments.Models.Document>

Change this code so it looks like this:


Hide Copy Code

@model PagedList.IPagedList<MvcDocuments.Models.Document>

Now look for the <tr> part in the code and the following type of code:
Hide Copy Code
<th>

@Html.DisplayNameFor(model => model.Document_date)

</th>

This code wont work with the PagedList so we are going to change all of this to the following:
Hide Shrink
<tr>
<th>

Copy Code

Document Date:
</th>
<th>
Company Name:
</th>
<th>
Mail Category:
</th>
<th>
Costs Group:
</th>
<th>
Payment Status:
</th>
<th>
Reference:
</th>
<th>
Note:
</th>
<th>
Amount Ex VAT:
</th>
<th>
VAT:
</th>
<th>
Amount:
</th>
<th>
URI;
</th>
</tr>

When done go to the bottom of the page were it says </table> and add after that the following
code:
Hide Shrink

Copy Code

<div>
Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber)of
@Model.PageCount
@if (Model.HasPreviousPage)
{
@Html.ActionLink("<<", "Index", new { page = 1, sortOrder =
ViewBag.CurrentSort, currentFilter=ViewBag.CurrentFilter })
@Html.Raw(" ");
@Html.ActionLink("< Prev", "Index", new { page = Model.PageNumber - 1,
sortOrder = ViewBag.CurrentSort, currentFilter=ViewBag.CurrentFilter })
}
else
{
@:<<
@Html.Raw(" ");
@:< Prev
}
@if (Model.HasNextPage)
{
@Html.ActionLink("Next >", "Index", new { page = Model.PageNumber + 1,
sortOrder = ViewBag.CurrentSort, currentFilter=ViewBag.CurrentFilter })
@Html.Raw(" ");
@Html.ActionLink(">>", "Index", new { page = Model.PageCount, sortOrder =
ViewBag.CurrentSort, currentFilter=ViewBag.CurrentFilter })
}
else
{
@:Next >
@Html.Raw(" ")
@:>>
}
</div>

Now Go to the BUILD Menu Option in Visual Studio and Click on the Rebuild Solution Option
and then hit F5 , if you have done the above steps and go to the Documents you will get this
View:

I didn't add records yet to this sample but if you have more then two records in your Documents
database then the Paging will work.

Adding paging involves as you have seen some work for all the pages you want it.

2. Add Search functionality


The Next step we are going to do is adding some Search functionality, the first step to do that is
on the View Page so open the Index.cshtml page and Add the following code just above were the
<table> parts starts:
Hide Copy Code
@using (Html.BeginForm())
{
<p> Find Relation: @Html.TextBox("SearchString")
<input type="submit" value="Find" /> </p>
}
<table>...

This will show a Search Box on the Page and a Button with the Text Find in it. This is it for the
Index.cshtml Page, go to the Solution Explorer again and open the DocumentController.cs file.

Change the ViewResult Index (The method that returns the Index page) so that it is as the
following code:
Hide Shrink

Copy Code

public ViewResult Index(string sortOrder, string currentFilter , string


searchString , int? page)
{
ViewBag.CurrentSort = sortOrder;
ViewBag.DateSortParm = sortOrder == "Date" ? "Date desc" : "Date";
if (Request.HttpMethod == "GET")
{
searchString = currentFilter;
}
else
{
page = 1;
}
ViewBag.CurrentFilter = searchString;
var document = from d in db.Documents
select d;
if (!String.IsNullOrEmpty(searchString))
{
document = document.Where(d =>
d.Company.Company_name.ToUpper().Contains(searchString.ToUpper()));
}
switch (sortOrder)
{

case "Date":
document = document.OrderBy(d => d.Document_date);
break;
case "Date desc":
document = document.OrderByDescending(d => d.Document_date);
break;
default:
document = document.OrderByDescending(d => d.Document_date);
break;

}
//Pager
int pageSize = 2;
int pageNumber = (page ?? 1);
//Return content
return View(document.ToPagedList(pageNumber, pageSize));
}

When you Hit the F5 button and you go to the Documents Page you will see that the Search Box
and Button are Added, type the name of one of your Relations or just a few first letters as I did
(co for CodeProject) and you get only records from that relation:

TASK: OK this is the moment that you can Add the Paging and Search functionality into your
pages and controllers, because I want this sample to Work I have done that in the Contacts,
Companies and Documents Pages and Controllers in the provided sample but you can do the
above steps yourself if you want.

3. Add Alphabetical Sorting


As you may have noticed in the previous Image the Documents are sorted on a Descending Date,
so the most current record is on top and if there are documents were the time is entered such as
25/04/2014 14:57 the sorting will take also place based on the time so the most recent document
will be on top.

For documents we want the sorting based on the Date but for Companies we want them to be
presented Alphabetically.
When you open the CompaniesController.cs file
Hide Copy Code
public ActionResult Index()
{
var companies = db.Companies.Include(c => c.State).Include(c => c.Country);
return View(companies.ToList());
}

And you add the following code behind the .Include(c => c.Country); part:
Hide Copy Code

.OrderBy(c => c.Company_name)

So the code looks like this:


Hide Copy Code
public ActionResult Index()
{

var companies = db.Companies.Include(c => c.State).Include(c =>


c.Country).OrderBy(c => c.Company_name);
return View(companies.ToList());
}

You will see that sorting based on the Alphabet takes place.
Note: In the above shown code we didn't add Search functionality to the CompanyController.cs
and the Index.cshtml file of the Company View in the View folder, in the MVCDocuments
Sample part 2 download Search functionality is added also.
TASK: The above shown code is the code before you added the Paging and Search functionality
to it so your code should look different if you have done the previous TASK but you know were
to look to Add the Sorting order to your code and in the provided Sample code this is
implemented also.

4. Make it Private
The next thing we are going to do is make the pages private so only people who are logged in
can view the page. We go back to the Solution Explorer and Open the Document folder and in
that the Index.cshtml page. Just below the <h2>Index</h2> tag Enter the following line of code:
Hide Copy Code
<h2>Index</h2>

@if(User.Identity.IsAuthenticated) {

<span>

Now go to the bottom of the page and below the closing tag of the </div> add the following
code:
Hide Copy Code
</span>

When you now hit F5 and you go to the Documents you get the following screen:

Note: If you see the documents most likely you are Logged In. Of course any one who registers
can view your records in this sample but if you get rid of the Register option the records are
private.
TASK: Now change all the pages and make them private, so not only the Index.cshtml pages but
all pages per folder.

5 Create the Upload


The first thing we are going to do is create a folder were we are going to receive the uploaded
files. Go to the Solution Explorer and Right Click with your mouse on that and select Add and
then Select New Folder:
Give this folder the name: Assets , when done a new folder is added to the solution:

Now Right Click on the Assets Folder and Select Add again and Select New Folder and call this
folder: Documents so it looks like this:

Now go to the Views Folder and go to the Document Folder and Right Click with your mouse on
that and select Add View. Give this new View the Name: DocumentUpload and don't change
anything else just Click on the Add button:

The DocumentUpload.cshtml file will be created and you will see this code:
Hide Copy Code
@{

ViewBag.Title = "DocumentUpload";
}
<h2>DocumentUpload</h2>

We are going to change this code to the following:


Hide Copy Code
@@{

ViewBag.Title = "Upload Document";


}
@if(User.Identity.IsAuthenticated) {
<span>
<h2>Upload Document</h2>
<form action="" method="post" enctype="multipart/form-data">
<table>
<td>
<label for="file">Filename</label></td>
<td>
<input type="file" name="file" id="file" />
</td>
<td>
<input type="submit" value="Upload" />
</td>
</table>
</form>
</span>

} else
{
<span>You need to Login to View this page!</span>
}

The upload page will look like this:

That's it for this page, now open the Index.cshtml page in the Document folder and look for this
part:
Hide Copy Code
<p>

@Html.ActionLink("Create New", "Create")


</p>

Change this part to:


Hide Copy Code
<p>
@Html.ActionLink("Create New", "Create") @Html.ActionLink("Upload Document",
"DocumentUpload")
</p>

This will present the link to the upload Page:

Thats it for the pages, now go to the Controllers folder in the Solution Explorer and go to the
DocumentController.cs file and open that. Go to the using part and Add the following using
directive: using System.IO; , so it matches as shown below:
Hide Copy Code
using
using
using
using
using
using

System;
System.Collections.Generic;
System.Data;
System.Data.Entity;
System.Linq;
System.Web;

using
using
using
using

System.Web.Mvc;
PagedList;
System.IO;
MvcDocuments.Models;

Now go to the bottom of all the code of this DocumentController and add the following code
behind this part:
Hide Copy Code
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}

So after this closing: } (bracelet) you enter this code:


Hide Copy Code

public ActionResult DocumentUpload()


{
return View();
}
[HttpPost]
public ActionResult DocumentUpload(HttpPostedFileBase file)
{
string path = null;
if (file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
path = AppDomain.CurrentDomain.BaseDirectory + "Assets\\Documents\\" +
fileName;
Response.Write(path.ToString());
file.SaveAs(path);
}
return RedirectToAction("Index");
}
public ActionResult OpenFile()
{
return View();
}

Now go to the Solution Explorer Folder and open the View folder and select the Index.cshtml file
and look for this line of code:
Hide Copy Code

<td>
@Html.DisplayFor(modelItem => item.Document_uri)
</td>

Change this code so it matches as shown below:


Hide Copy Code
<td>

@Html.DisplayFor(modelItem => item.Document_uri)


<a href="~/Assets/Documents/@Html.DisplayFor(model =>
item.Document_uri)"target="_blank">View Document</a>
</td>

This will add a Link to the uploaded document on the page. Be aware that the process intended is
to scan a document you receive with the standard mail and save this document as .PDF format
and upload it. You have to name the document as it is, so for example when you have a document
called Manual1246.PDF you have to make sure that the .PDF file extension is behind the name
of the .PDF document.
When Clicked on the link you will be presented with the Uploaded .PDF document:

There is one more thing I have done and that is changing this following code so pages are
showing an other title:
Hide Copy Code
@{

ViewBag.Title = "Documents";
}
<h2>Documents</h2>

I have changed the Viewbag.Title into Documents so it shows that and I have changed the
<h2> part so it shows Documents instead of Index and I did that with Contact and Company
also so it's more clear on what page you are when using the application

6 Add Validation
There is one more thing I want to Add to the Application and that is making sure that all fields
are filled in so no empty data will be passed to the database so I have changed the Classed. Have
a look at the Document.cs Class (In the Models Folder in the Solution Explorer) and change it so
it looks like this:
Hide Shrink

Copy Code

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MvcDocuments.Models
{
public class Document
{
//Identifier
public int DocumentId { get; set; }
//Document date
[Required]
public DateTime Document_date { get; set; }
//Company
public int CompanyId { get; set; }
public virtual Company Company { get; set; }
//Mail category
public int Mail_categoryID { get; set; }
public virtual Mail_category Mail_category { get; set; }
//Costs group
public int Costs_groupId { get; set; }
public virtual Costs_group Costs_group { get; set; }
//Payment status
public int Payment_statusId { get; set; }
public virtual Payment_status Payment_status { get; set; }
//Bill
[Required]
public string Reference { get; set; }
//Note
[Required]
public string Note { get; set; }
//Financial
[Required]
public double AmoutExVat { get; set; }
[Required]
public double Vat { get; set; }
[Required]
public double Amount { get; set; }
//.PDF Link
[Required]
public string Document_uri { get; set; }
}
}

As you can see we have added the following Using Directives:


Hide Copy Code

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

And we have added above the variables:


Hide Copy Code
[Required]

If you have done the same and hit F5 you will get an Error that things have changed so we first
have to update the database, to do that we go back to the Package Manager Console we used in
Part One of this sample (TOOLS > NuGet Package Manager > Package Manager Console ) and
type in:
Hide Copy Code
PM> Add-Migration "DatabaseChanged"

Between the you can type in what you want it's just the name you give to this migration. Then
hit Enter and the Migration will be created in the Migrations Folder in the Solution Explorer.
Now type in the Package Manager Console:
Hide Copy Code

PM> Update-Database

The database will be updated and when you now go to the Documents and select Create New and
Click on the Create button you will get this screen:

To make it clear. When you make changes to the Classes in the Model folder you have to do
these steps of Adding a migration otherwise it won't work, if something goes wrong and updating
your Database fails just Delete the Migration and start over again. There is one other thing I want
to make changes to and that is the sorting of the lists when you create a new document or contact
or where ever you use Lists in your application.

Let's have a look at the Create Method in the DocumentController.cs file, it looks like this:
Hide Copy Code
public ActionResult Create()
{
ViewBag.CompanyId = new SelectList(db.Companies,"CompanyId",
"Company_name");
ViewBag.Mail_categoryID = new SelectList(db.Mail_categories,
"Mail_category_name");
ViewBag.Costs_groupId = new SelectList(db.Costs_groups, "Costs_groupId",
"Cost_group_name");
ViewBag.Payment_statusId = new SelectList(db.Payment_statusses,
"Payment_statusId", "Payment_status_name");
return View();
}

We have to change the code so it matches the following:


Hide Copy Code
public ActionResult Create()
{
ViewBag.CompanyId = new SelectList(db.Companies.OrderBy(x =>
x.Company_name), "CompanyId", "Company_name");
ViewBag.Mail_categoryID = new SelectList(db.Mail_categories.OrderBy(x =>
x.Mail_category_name), "Mail_categoryId", "Mail_category_name");
ViewBag.Costs_groupId = new SelectList(db.Costs_groups.OrderBy(x =>
x.Cost_group_name), "Costs_groupId", "Cost_group_name");
ViewBag.Payment_statusId = new SelectList(db.Payment_statusses.OrderBy(x =>
x.Payment_status_name), "Payment_statusId", "Payment_status_name");
return View();
}

This .OrderBy(x => x.Cost_group_name) takes care of presenting the List in a Alphabetical
Order.

Thats it for this part of the MVCDocuments Sample. I hope you enjoyed my writings so far and
perhaps this application is of some practical use for you.

Points of Interest
Thats it for this part of the MVCDocuments Sample. I hope you enjoyed my writings so far (I'm
thinking about a next part about making it look much nicer with Html5 and JavaScript). I hope
that this application is of some practical use for you. My personal version stores around one
thousand documents in .PDF format and I use it regular to look things up.