I am actually more confused rather than understanding the concept. I have been developing a system and want to know the MVC design pattern. which one is best and the concept and usability of the layers?
In general, I have two approaches:
1.
ViewModel layer (contains viewmodels), Models (contains models and datacontext), Repository (communicating to datacontext), Controller (communicating to view), Presentation (views)
In general, if one page for example, country (crude operations) will be look like this
[AdminRoleAuthorize(Roles = "Admin")][CustomHandleError]
public class CountriesController : BaseController
{
#region Members
private IUnitOfWork unitOfWork;
#endregion Members
#region Constructor
public CountriesController(iMSTUnitOfWork _unitOfWork)
{
unitOfWork = _unitOfWork;
}
#endregion Constructor
#region Actions
public ActionResult Index()
{
return View();
}
public async Task<ActionResult> Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Country country = await unitOfWork.CountryRepository.GetByIdAsync((int)id);
if (country == null)
{
return HttpNotFound();
}
return View(country);
}
public ActionResult Create()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create(Country country)
{
try
{
if (ModelState.IsValid)
{
unitOfWork.CountryRepository.Insert(country);
await unitOfWork.SaveAsync();
return RedirectToAction("Index");
}
return View(country);
}
catch (Exception ex)
{
ModelState.HandleError(ex);
return View(country);
}
}
public async Task<ActionResult> Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Country country = await unitOfWork.CountryRepository.GetByIdAsync((int)id);
if (country == null)
{
return HttpNotFound();
}
return View(country);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(Country country)
{
try
{
if (ModelState.IsValid)
{
var original= unitOfWork.CountryRepository.GetById(country.Id);
unitOfWork.CountryRepository.Update(original);
await unitOfWork.SaveAsync();
return RedirectToAction("Index");
}
return View(country);
}
catch (Exception ex)
{
ModelState.HandleError(ex);
return View(country);
}
}
public async Task<ActionResult> Delete(int id)
{
await unitOfWork.CountryRepository.DeleteAsync(id);
await unitOfWork.SaveAsync();
return RedirectToAction("Index");
}
#endregion Actions
#region DataTable
public JsonResult GetJsonData(DTParameterModel param)
{
try
{
var results = GetCountry(param);
return Json(results, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
return Json(new { error = ex.Message });
}
}
#endregion DataTable
#region Methods
public DTResult<Country> GetCountry(DTParameterModel param)
{
var errors = unitOfWork.CountryRepository.GetQueryable().Where(a => (a.Name.Contains(param.Search.Value) || param.Search.Value == null) );
return DataTableFiltering<Country>.GetResult(param, errors);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
// unitOfWork.Dispose();
}
base.Dispose(disposing);
}
#endregion Methods
}
Please note that there is no business layer comes here and I am accessing repository directly.
2. ViewModel layer (contains viewmodels), Models (contains models and datacontext), Repository (communicating to datacontext), Controller (communicating to view), Presentation (views) Business layer
In this scenario my code will look like this:
public class ParticipationStatusController : BaseController
{
private readonly IParticipationStatusManager _participationStatusManager;
public ParticipationStatusController(IParticipationStatusManager participationStatusManager, ISecurityManager securityManager) : base(securityManager)
{
_participationStatusManager = participationStatusManager;
}
#region NotUsed
public async Task<ActionResult> ParticipationStatusListList()
{
var serviceResponse = new DataResponse<string> { ErrorCode = ErrorCodes.Failure };
var clientId = GetAuthenticatedClientId();
if (clientId == 0)
{
serviceResponse.Message = HttpStatusCode.Unauthorized + " :Set Authenticated Client Id";
return View(serviceResponse);
}
int languageId = await GetClientLanguageId(clientId);
var response = await _participationStatusManager.GetParticipationStatus(languageId);
if (!response.Exceptions.Any())
{
if (response.Response != null)
{
var resultResponse = new DataResponse<IEnumerable<ParticipationStatusTranslateViewModel>>
{
Data = response.Response
};
ErrorMessage.Getmessage(response.Response.Count(), "Participation Status", ref resultResponse);
return Ok(resultResponse);
}
else
return NotFound();
}
foreach (var keyValuePair in response.Exceptions)
{
ModelState.AddModelError(keyValuePair.Key, new Exception(keyValuePair.Value));
}
if (response.Response != null)
return View(response.Response);
else
return BadRequest(ModelState);
}
#endregion
}
Please note that all the communications to database are going through the business layer which is communicating to the repository.
Which is a good to use and what is the role of each layer? I do not have good experience developing system design.
Also, should I use viewmodel only in presentation? and use automapper to communicate to the repository?