Introduction
EntityUI
is basically an idea to be able to rapidly generate your application by automatically creating the User Interface and the Database repository in ASP.NET applications using Code First approach. As developers, you would write your Domain and View Models, and adjust those classes to create your application, without writing much code.
Working Demo
You can visit http://www.razisyed.com/entityui for a working demo and more details.
The source code is also available on git: https://github.com/razisyed/EntityUi
Background
I originally started on EntityUi
with ASP.NET a few years ago, and wrote some simple code that used reflection to render the UI. That's the original article I had posted. However, since I started on EntityUI, a lot has changed. MVC and Knockout have been mainstream now for a while, and they are both excellent tools to implement the MVVM pattern.
So EntityUi
is now a project that uses MVC and Knockout to automatically generate the UI from the model. It's basically aiming to be a rapid application development tool, to not just quickly generate common crud pages, but also attempt to handle much more advanced scenarios.
Pre-Requisite
This is for a Microsoft MVC project. You should be familiar with MVVM pattern, Domain Model, View Model, and need knockout knowledge to understand and use some of the advanced features. You also need to know Repository pattern and Microsoft Entity Framework Code First to fully understand how this all works. We will use nuget to download the EntityUi package, and bootstrap for a beautiful layout.
Using the Code
I'll demonstrate the usage with a brand new project to keep things simple. Start a blank MVC project, and then add 2 Class Library Projects to the Solution, one for Domain Model, and the other for Repository.
Then add EntityUi from nuget to the Domain Project and Repository Project in the solution. To install EntityUi, run the following command in the Package Manager Console:
PM> Install-Package EntityUi
In the blank MVC project, install the EntityUi.Web
package:
PM> Install-Package EntityUi.Web
The EntityUi package has the following core concepts:
DomainModelBase
- Base class that your Domain Model (really Data Model) objects need to inherit from. ViewModelBase
- Base class that your View Model objects need to inherit from. ControllerBase
- Base class for your Controller, it provides Crud methods built in. - RepositoryBase - Base class for your Repository, it provides Crud methods built in using Entity Framework.
The EntityUi.Web
package adds several layouts and templates that are needed to use EntityUi.
Next, we need to write the Domain Model and Repository Methods.
In this example, we'll work with the following Sample "Department
" Class. I picked it up from MSDN Entity Framework Code First Fluent API example.
public class Department : DomainModelBase
{
public Department()
{
Courses = new HashSet<Course>();
}
public string Name { get; set; }
public decimal Budget { get; set; }
public DateTime StartDate { get; set; }
public int? Administrator { get; set; }
public ICollection<Course> Courses { get; set; }
}
As you can see, it is inherited from the DomainModelBase
class.
Next, let's setup the Repository. Add your Context
class, inherited from Entity Framework's DbContext
class, and add a simple Repository
class for Department
, "DepartmentRepository
":
public class DataContext : DbContext
{
public DbSet<Department> Departments { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer(new CreateDatabaseIfNotExists<DataContext>());
}
}
public class DepartmentRepository : RepositoryBase<Department, DataContext>
{
protected override DataContext GetContext()
{
return new DataContext();
}
}
The DataContext
class is a very simple Context
class with just one property for Departments
for now.
The Repository
is also a very simple implementation. This class doesn't have any methods other than GetContext
, and it is inherited from the DomainModelBase
class. As you can see, when inheriting from RepositoryBase
, you have to provide the Entity name and the DataContext
to the Base so it knows what it's working with.
Now let's move on to the View, and add the Model, View and Controller classes. I always promote a separate Domain and View Model classes, even though for simple cases they are mostly the same. We will use AutoMapper
to easily convert between Domain and View models.
So here is the Controller
Class:
public class DepartmentController : ControllerBase<Department, DepartmentView, DataContext>
{
public DepartmentController()
{
Repository=new DepartmentRepository();
}
}
The controller is inherited from ControllerBase
, similar to the other classes. It needs to know the Domain Model, View Model and the DataContext
.
You need to map the properties between the Domain Model and the View Model to convert them to one another. EntityUi
automatically creates a default Mapper for you where the values are copied if the property names are the same.
If you want, you can also setup a custom mapping between the Domain and View Model objects in global.aspx for AutoMapper
:
Mapper.CreateMap<Department, DepartmentView>();
Mapper.CreateMap<DepartmentView, Department>()
.ForMember(d => d.Id, o => o.Condition(s => s.Id > 0))
.ForMember(d => d.Courses, o => o.Ignore());;
The above is a simple Domain View to Model View mapping using AutoMapper
. Behind the scenes, it basically uses reflection to copy the property values from one object to another. Basically with this tool, we are telling EntityUi
how to convert between the Domain and Model view objects.
Now you should be able to build and run the application, and when you navigate to "department
", it should render the department screen for you, which includes complete crud functionality, including rendering pages and saving it to the database.
So this is the most basic and simplistic use of EntityUi
. Let's try something a little more interesting now.
Using Drop Down
Here is how to use a drop down list by just modifying your view Model. Let's start by adding Course
concept as follows:
Here is the Domain Model:
public class Course : DomainModelBase
{
public Course()
{
Instructors = new HashSet<Instructor>();
}
public string Title { get; set; }
public int Credits { get; set; }
public int DepartmentID { get; set; }
public Department Department { get; set; }
public ICollection<Instructor> Instructors { get; set; }
}
As you can see, it has Department
as a Navigation Property, which indicates that in the UI, we'd like to see a drop down that lists all the Departments
, and the user should be able to select the department
.
Here is the Repository
and the Controller
:
public class CourseRepository : RepositoryBase<Course, DataContext>
{
protected override DataContext GetContext()
{
return new DataContext();
}
}
They are both just bare bones, by simply inheriting from EntityUi
's RepositoryBase
and Controller Base.
Now, here is the Model View:
public class CourseView : ViewModelBase
{
public string Title { get; set; }
public int Credits { get; set; }
public DropDown Departments { get; set; }
public CourseView()
{
Departments = new DropDown
{
Items = (new DepartmentRepository())
.List()
.ToList()
.ConvertAll(x => new SelectListItem
{
Text = x.Name,
Value = x.Id.ToString()
})
};
}
}
This is a little different. To render a dropdown list for Department
, we defined the Departments
Property as EntityUi
's helper type "DropDown
". Also, in the constructor, we load it up with a list of Departments
from the database. I hope the code is self explanatory, and doesn't need too much explanation. All we are doing is calling the "List()
" method (provided by EntityUi
) on the DepartmentRepository
to get all the Departments
, and using "ConvertAll()
" method (provided by Linq) to convert it to SelectListItem
.
The next interesting part will be where we map the Model View and the Domain View. Here is the code that needs to be added to Global.asax:
Mapper.CreateMap<CourseView, Course>()
.ForMember(d => d.Id, o => o.Condition(s => s.Id > 0))
.ForMember(d => d.DepartmentID, o => o.MapFrom(s => s.Departments.SelectedId))
.ForMember(d => d.Department, o => o.Ignore());
Mapper.CreateMap<Course, CourseView>()
.ForMember(d => d.Departments, o => o.Ignore())
.AfterMap((s, d) => d.Departments.SelectedId = s.DepartmentID.ToString());
This is actually a fairly advanced use of Auto Mapper. You might want to look at AutoMapper
's documentation.
In the first Mapping statement, we are mapping the CourseView
(View Model) to Course
(Domain Model). The interesting part here is that we are mapping the Domain's Department
ID to the SelectedId
property in the View's Departments
Dropdown. In the second mapping, where we go from Domain to View Model, it's the exact reverse.
This is pretty much all the coding that's needed. If you run now and navigate to "Courses
", you will be able to add/edit/delete with Department
showing as a drop down:
Adding User Interface Interactions
So far, we have looked at some basic crud functionality. The idea is to be able to more than just crud by just working with Model View. So let's say we have a business requirement that the Department
should ask for budget only if Budget
is allocated, otherwise, the budget input should not be shown.
The best approach for this would be JavaScript in the view. One of the easiest ways to handle these scenarios is through knockout. EntityUi
allows you to add knockout binding to any property by using the DataBind
data annotation.
So we can accomplish this requirement by simply modifying the Department
View as follows:
public class DepartmentView : ViewModelBase
{
public string Name { get; set; }
public bool HasBuget { get; set; }
[DataBind("visible:HasBuget()")]
public decimal Budget { get; set; }
public DateTime StartDate { get; set; }
}
So what I did here is that first I added a boolean property HasBudget
. This would be rendered as a checkbox
.
Next, I added the DataBind
attribute and provided my knockout binding that I would have generally added to the view. EntityUi
automatically renders it. You need to be familiar with knockout bindings to fully utilize this feature, and if not, please visit www.knockoutjs.com for documentation. All we are doing here is setting the visibility to the HasBudget
property. Behind the scene, EntityUi
uses knockoutmvc to setup each Model View as knockout view model, making each property observable.
What this code change will do is that when you view the page in edit mode, it will show the Budget input field and label when you check the "HasBudget
" checkbox, and it will hide them if you uncheck them.
Summary
So hopefully with the details provided above, you can see how EnitityUi
can be used for Rapid Application Development using tools to handle all aspects for code writing, from working with Data all the way to the User Interface.
As developer, the main task is to write the Domain Model and View Model. Then, most of the other things will happen by adding Attributes and/or Fluent API configuration and following conventions, and we will have a fully functional application.
EntityUi
is also very flexible, and provides full control to the developer. Developers can overload or add any method to any of their class, whether it's the Repository, Controller or View. You can also very easily write complete pages or classes on your own within the same application without utilizing EntityUi
, or add to the view and controller that utilizes EntityUi
's framework.
References
I wrote EntityUi
using many different open source libraries. Here are some of the main ones: