ASP.NET MVC with Unity Introduction
- Install the nuget package “Unity.Mvc”
- Make sure that the following classes have been added to your App_Start folder:
- UnityConfig.cs
- UnityMvcActivator.cs
- Navigate to the UnityConfig class, method RegisterTypes(IUnityContainer container) and start mapping your Interface/Class dependencies. For example, if you have an Email Service that some parts of your application will need to depend on, you will need to create an Interface IEmailService.cs with an implementation class EmailService.cs
public static void RegisterTypes(IUnityContainer container) { // TODO: Register your type's mappings here. container.RegisterType<IEmailService, EmailService>(); }
- Now that you have registered your mappings, you can then begin injecting these dependencies wherever they are needed. Examples below:
public class HomeController : Controller { public readonly IEmailService _emailService; public HomeController(IEmailService emailService) { _emailService = emailService; } public ActionResult SendEmail(string title, string email, string message) { _emailService.Send(title, email, message); return null; } }
Maybe on a separate controller too?public class FormsController : Controller { public readonly IEmailService _emailService; public FormsController(IEmailService emailService) { _emailService = emailService; } public ActionResult SendEmail(string title, string email, string message) { _emailService.Send(title, email, message); return null; } }
- OPTIONAL: If you have a Unit Test project, then you can pass on a different mapping to your interface like the below:
container.RegisterType<IEmailService, TestEmailService>();
Example of Implementation
Step 1: Create Class Library Project for example Repository and add an interface IRepository as given below for generic operations implementation.
Step 1: Create Class Library Project for example Repository and add an interface IRepository as given below for generic operations implementation.
public interface IRepository<T> where T : class
{
T Find(Expression<Func<T, bool>> predicate);
T GetById(Int64 id);
T IQueryable<T> GetAll();
T IQueryabl<T> Search(Expression<Func<T, bool>> predicate);
bool IsExists(Expression<Func<T, bool>> predicate);
int Insert(T entity);
int Delete(T entity);
int Update(T entity);
}
Step 2: Add Folders like Masters, Transactions etc in this project and put all other class related interface in these folders and inherit them with IRepository interface. You may put function definitions other than generics implementation above.
public interface ITaskAllocation : IRepository<Task_Allocation_Model)
{
string ExcecuteTaskAllocation(Task_Allocation_Model obj);
}
Note : For every model add interface as above and models used in above class should in Models class library.
Step 3: In Helpers class library we will be putting all the Helpers containing implementations of Methods declared in interface. We will be using base class for implementations of Generic Methods implementation declared in Generic Interface IRepository above and inherit them with all other helpers classes.
For example we will putting TaskAllocationHelper class for ITaskAllocation Interface.
i) Put BaseClass in Common Folder in Helper Class Library. Base Class Generic Implementation is given below.
public class BaseClass<T> : IDisposable, IRepository<T> where T : class
{
private readonly ApplicationDbContext _dbContext;
public readonly int unit;
public readonly string log;
public BaseClass()
{
if(HttpContext.Current.User.Identity.IsAuthenticated)
{
if(_dbContext == null)
_dbContext = new ApplicationDbContext();
if(unit == 0)
unit = ApplicationSession.GetUserDetails().UM_CORP_UNIT;
if(string.IsNullOrEmpty(log)
log = CommonFunction.GetEntryLog(ApplicationSession.GetUserDetails().UM_UID);
}
public virtual T GetById(Int64 id)
{
_dbContext.Set<T>().Find(id);
}
public virtual IQueryable<T> GetAll()
{
_dbContext.Set<T>().AsQueryable();
}
public virtual IQueryable<T> Search(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
_dbContext.Set<T>().Where(predicate).AsQueryable();
}
public virtual bool IsExists(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
_dbContext.Set<T>().Any(predicate);
}
_return _dbContext.SaveChanges();
}
public int Update(T entity)
_return _dbContext.SaveChanges();
}
public int Delete(T entity)
_return _dbContext.SaveChanges();
}
public void Dispose()
{
if(_dbContext != null)
{
_dbContext.Dispose();
return;
}
}
public virtual T GetById(Int64 id)
{
_dbContext.Set<T>().Find(id);
}
public virtual IQueryable<T> GetAll()
{
_dbContext.Set<T>().AsQueryable();
}
public virtual IQueryable<T> Search(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
_dbContext.Set<T>().Where(predicate).AsQueryable();
}
public virtual bool IsExists(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
_dbContext.Set<T>().Any(predicate);
}
public int Insert(T entity)
{
_dbContext.Set<T>().Add(entity);_return _dbContext.SaveChanges();
}
public int Update(T entity)
{
_dbContext.Entry(entity).State = EntityState.Modified;_return _dbContext.SaveChanges();
}
public int Delete(T entity)
{
_dbContext.Set<T>().Remove(entity);_return _dbContext.SaveChanges();
}
public void Dispose()
{
if(_dbContext != null)
{
_dbContext.Dispose();
return;
}
}
}
}
ii) Put Helper classes in specific Folders like Masters, Transactions in Helper Class Library.
public class TaskAllocationHelper : BaseClass<Task_Allocation_Model>, ITaskAllocation
{
public string ExcecuteTaskAllocation(Task_Allocation_Model obj)
{
string msg=string.Empty;
try
{
obj.Unit=base.Unit;
if(obj.ActionType==(int)CrudType.Add)
{
if(!base.IsExists(x=>x.Unit == obj.Unit)
msg=CommonFunction.GetOperationStatusMsg(base.Insert(obj),"AddSuccess");
else
msg=CommonFunction.GetOperationStatusMsg(-1,"AlreadyExists");
}
else if(obj.ActionType==(int)CrudType.Edit)
{
msg=CommonFunction.GetOperationStatusMsg(base.Update(obj), "UpdateSuccess");
}
else if(obj.ActionType==(int)CrudType.Delete)
{
obj.Status = 2; // Changing record status as deleted for soft delete operation.
msg=CommonFunction.GetOperationStatusMsg(base.Update(obj), "Delete");
}
}
catch(Exception ex)
{
msg = CommonFunction(-2, "SystemError");
return msg;
}
}
}
Step 4: Mapping in UnityConfig Registration in RegisterTypes Method in AppStart Folder.
public static void RegisterTypes(IUnityContainer container) {
// TODO: Register your type's mappings here.
container.RegisterTypes<ITaskAllocation, TaskAllocationHelper>();
container.RegisterType<IEmailService, EmailService>();
}
Step 5: In Controller, Now that you have registered your mappings, you can then begin injecting these dependencies wherever they are needed as given below:
public class HomeController : Controller {
public readonly ITaskAllocation _taskAllocation; public readonly IEmployee _emp;
public HomeController(ITaskAllocation taskAllocation, IEmployee emp)
{
this._emp=emp;
this._taskAllocation = taskAllocation; }
public ActionResult TaskAllocation() {
return View(_taskAllocation.Search(x=>x.Status != CrudState.Deleted).ToList());
}
[HttpPost]
[ValidateAntiforgery]
public JavaScriptResult TaskAllocation(Task_Allocation_Model obj)
{
if(ModelState.IsValid)
return JavaScript(_taskAllocation.ExcecuteTaskAllocation(obj));
else
return JavaScript(CommonFunction.GetOperationStatusMsg(1,CommonFunction.GetModelError(ViewData.ModelState));
}
public PartialViewResult Search(int code, string desc)
{
var result =_taskAllocation.Search(x=>(code==0 ||x.Code==code) && (desc == null || x.Desc.ToLower().Contains(desc.ToLower())) && x.Status != CrudState.Deleted).ToList();
return PartialView("~/Views/Shared/Tasks/_TaskListPartial.cshtml", result);
}
Step 6 : View TaskAllocation.cshtml
@model IEnumable<Models.Task_Allocation_Model>
@using Helpers.Common
@{
Viewbag.Title="";
Models.CommonModel obj=new Models.CommonModel();
}
<div class="">
<div>
<input id="txtCode" type="number" oninput="javascript:if(this.value.length> this.maxLength) this.value=this.value.Slice(0,this.maxLength); maxLength="5" />
<input id="txtCode" type="text" maxLength="5" />
<input id="btnSearch" type="button" value="Search" />
</div>
<div class="panel panel-primary filterable" id="divListPartial">
@{ Html.RenderPartial("~/Views/TaskListPartial.cshtml"); }
</div>
</div>
<div id="divPartial"></div>
@section scripts {
<script type="text/javascript">
$( document ).ready(function() {
$("#btnSearch").click(function (){
var code = $("#txtCode").val();
var desc=$("#txtDesc").val();
if(code=="")
code=0;
if(desc="")
desc=null;
$.ajax({
type: "POST",
url: '/Home/Search',
data: '{code: code, desc:desc }',
success: function (result) {
$("#divListPartial").html(result);
$('table').DataTable();
},
error: function () {
alert("Error..");
}
});
});
}
In Listing Partial View TaskListPartial.cshtml
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.TaskNo)
</th>
<th>
@Html.DisplayNameFor(model => model.TaskName)
</th>
<th>
@Html.DisplayNameFor(model => model.TaskDesc)
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.TaskNo)
</td>
<td>
@Html.DisplayFor(modelItem => item.TaskName)
</td>
<td>
@Html.DisplayFor(modelItem => item.TaskDesc)
</td>
@{ Html.RenderPartial("~/Views/Shared/_ListViewActionPartial.cshtml", Tuple.Create(item.ID,Common,LoadModal,'_TaskPartial.cshtml')); }
</tr>
}
</table>
In _ListViewActionPartial.cshtml View :
@model Tuple<int, string, string, string>
@{
int edit=Models.Common.CommonModel.CrudType.Edit.GetHashCode();
int delete=Models.Common.CommonModel.CrudType.Delete.GetHashCode();
int view=Models.Common.CommonModel.CrudType.View.GetHashCode();
}
<a class="glyphicon glyphicon-edit edit" title="Edit" onclick="showModal('@Model.Item1, @Model.Item2, @Model.Item3, @edit, @Model.Item4')">
<a class = "glyphicon glyphicon-delete delete" title = "Delete" onclick = "showModal('@Model.Item1, @Model.Item2, @Model.Item3, @delete, @Model.Item4')">
<a class="glyphicon glyphicon-view view" title="View" onclick="showModal('@Model.Item1, @Model.Item2, @Model.Item3, @view, @Model.Item4')">
In TaskPartial.cshtml : This partial view is used to add, edit or view Task.
In Common Controller : Action in Common Controller is used to return TaskPartial.cshtml.
[CustomAuthorize]
public class CommonController : Controller
{
public readonly ITaskAllocation _taskAllocation;
public readonly IEmployee _emp;
public CommonController(ITaskAllocation taskAllocation, IEmployee emp)
{
this._emp=emp;
this._taskAllocation = taskAllocation;
}
[HttpPost]
public PartialViewResult LoadModal(CommonModel model)
{
dynamic obj=null;
if(model.ActionType != CrudType.Add.GetHashcode())
{
if(model.partialViewName="_TaskPartial.cshtml")
obj=_taskAllocation.Search(x=>x.ID == model.ID).FirstOrDefault();
else if(model.partialViewName="_EmpPartial.cshtml")
obj=_emp.Search(x=>x.ID == model.ID).FirstOrDefault();
}
else
{
if(model.partialViewName="_TaskPartial.cshtml")
obj= new Task_Allocation_Model() { TaskId = CommonFunction.GetMaxTaskId("tblTaskAllocation","TaskId")};
else if(model.partialViewName="_EmpPartial.cshtml")
obj= new Emp_Model() { EmpId = CommonFunction.GetMaxTaskId("tblEmp","EmpId")};
}
if(obj!=null)
obj.ActionType=model.ActionType;
return PartialView("~/View/Shared/"+model.partialViewName, obj);
}
}
// todo :
Add Partial Views, common controller, scripts, custom authorize, exception logging
putting model and common function ex for more clarification, GetMaxTaskId function
ConvertToMsg renamed to getoperationstatusmsg