using System; using System.Collections.Generic; using System.Data.Entity.Validation; using System.IO; using System.Linq; using System.Security; using System.Web.Mvc; using System.Web.Routing; using MileageTraker.Web.Attributes; using MileageTraker.Web.DAL; using MileageTraker.Web.Models; using MileageTraker.Web.ViewModels; using MileageTraker.Web.ViewModels.CreateLog; namespace MileageTraker.Web.Controllers { [Authorize(Roles = "Driver, Administrator, Developer")] public class CreateLogController : ControllerBase { private const string CookeNameVehicleid = "mr_vehicleId"; private const string CookieKeyLogtype = "mr_logType"; public ViewResult Index() { var createLogModel = NewCreateLogModel(); return View(createLogModel); } [HttpPost] public ActionResult Index(CreateLogViewModel model) { if (ModelState.IsValid) { var confirmCreateLogViewModel = new ConfirmCreateLogViewModel(model); confirmCreateLogViewModel.Purpose.Available = GetPurposeTypesSelectList(); return View("Confirm", confirmCreateLogViewModel); } model.Purpose.Available = GetPurposeTypesSelectList(); return View(model); } [LogOwnerAuthorize] public ActionResult EditPast(int id) { var log = DataService.GetLog(id); var viewModel = new EditPastViewModel(log) { Purpose = { Available = GetPurposeTypesSelectList() } }; return View(viewModel); } [HttpPost] [ActionLog] public ActionResult EditPast(EditPastViewModel viewModel) { if (ModelState.IsValid) { var log = DataService.GetLog(viewModel.LogId); if (log.User.Username != User.Identity.Name) throw new SecurityException(); viewModel.SetProperties(log); if (viewModel.Purpose != null) log.Purpose = DataService.GetPurposeTypes() .First(pt => pt.PurposeTypeId == viewModel.Purpose.Selected); DataService.UpdateLog(log); TempData["StatusMessage-Type"] = "alert-success"; TempData["StatusMessage"] = @"You've successfully updated an entry traveling to " + viewModel.CityName + @" for " + log.Purpose.Purpose + @" on " + viewModel.Date.ToShortDateString() + @" in Vehicle Id " + viewModel.VehicleId + @" ending in " + viewModel.EndOdometer + @" miles on the odometer."; return RedirectToAction("Index"); } viewModel.Purpose.Available = GetPurposeTypesSelectList(); return View(viewModel); } [HttpParamAction] [HttpPost] public ViewResult Edit(CreateLogViewModel model) { model.Purpose.Available = GetPurposeTypesSelectList(); return View("Index", model); } [HttpParamAction] [HttpPost] [ActionLog] public ActionResult Confirm(CreateLogViewModel model) { if (ModelState.IsValid) { SetCookieValue(CookieKeyLogtype, model.LogType.Enum.ToString()); SetCookieValue(CookeNameVehicleid, model.VehicleId); // Save the new log var log = model.GetLog(); log.User = DataService.FindUserByUsername(User.Identity.Name); log.Source = HttpContext.Request.Url.AbsolutePath; log.UserHostAddress = HttpContext.Request.UserHostAddress; log.UserAgent = HttpContext.Request.UserAgent; log.Purpose = DataService.GetPurposeTypes() .First(pt => pt.PurposeTypeId == model.Purpose.Selected); DataService.AddLog(log); var editLink = Url.Action("EditPast", "CreateLog", new {id = log.LogId}); TempData["StatusMessage-Type"] = "alert-success"; TempData["StatusMessage"] = @"You've successfully created an entry traveling to " + model.CityName + @" for " + log.Purpose.Purpose + @" on " + model.Date.ToShortDateString() + @" in Vehicle Id " + model.VehicleId + @" ending in " + model.EndOdometer + @" miles on the odometer. " + @"Edit"; return RedirectToAction("Index"); } model.Purpose.Available = GetPurposeTypesSelectList(); return View("Index", model); } public PartialViewResult RecentLogs() { var username = User.Identity.Name; var user = DataService.FindUserByUsername(username); var logs = DataService.GetRecentLogsByUsername(user.Username); ViewData["name"] = user.FullName; return PartialView(logs); } private CreateLogViewModel NewCreateLogModel() { MileageLogType logType; Enum.TryParse(GetCookieValue(CookieKeyLogtype), true, out logType); var vehicleId = GetCookieValue(CookeNameVehicleid); return new CreateLogViewModel { LogType = logType, VehicleId = vehicleId, Date = DateTime.Today, Purpose = new SelectListViewModel { Available = GetPurposeTypesSelectList() } }; } #region Import public ActionResult ImportUpload() { return View(); } [HttpPost] public ActionResult Import(ImportUploadViewModel viewModel) { if (ModelState.IsValid && viewModel.File != null && viewModel.File.ContentLength > 0) { var fileName = Path.GetFileName(viewModel.File.FileName); var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName); viewModel.File.SaveAs(path); try { var logImports = LogImporter.Import(path); // todo: delete file? return View(logImports.ToList()); } catch (OutOfMemoryException) { TempData["StatusMessage"] = "Problem reading excel document - please verify that the document is in Excel 97-2003 Workbook (.xls) format"; TempData["StatusMessage-Type"] = "alert-error"; } catch (Exception ex) { TempData["StatusMessage"] = "Problem reading excel document: " + ex.Message; TempData["StatusMessage-Type"] = "alert-error"; } } return RedirectToAction("ImportUpload"); } enum ImportStatus { Success, Failure, Duplicate } [HttpPost] [ActionLog] public ActionResult ImportCreate(ImportLogViewModel viewModel) { var buttonAttributes = new Dictionary { { "class", "btn btn-mini" }, { "target", "_blank" } }; try { // verify purpose var purposeType = DataService.FindPurposeType(viewModel.Purpose); if (purposeType == null) { return Json(new { Status = ImportStatus.Failure.ToString(), Message = "Invalid Purpose: " + viewModel.Purpose, Action = GetFixLink(viewModel) }, JsonRequestBehavior.AllowGet); } if (!ModelState.IsValid) { var errorList = GetModelStateErrorList(ModelState); // remove the object name from the errors errorList = errorList.Select(s => s.Replace("viewModel.", "")); return Json(new { Status = ImportStatus.Failure.ToString(), Message = string.Join(", ", errorList), Action = GetFixLink(viewModel) }, JsonRequestBehavior.AllowGet); } var log = viewModel.GetLog(); log.Vehicle = DataService.GetVehicle(viewModel.VehicleId); log.User = DataService.FindUserByUsername(User.Identity.Name); log.Source = HttpContext.Request.Url.AbsolutePath; log.UserHostAddress = HttpContext.Request.UserHostAddress; log.UserAgent = HttpContext.Request.UserAgent; log.Purpose = purposeType; // check duplicate var duplicateLogs = DataService.GetDuplicateLogs(log).ToList(); if (duplicateLogs.Any()) { var link = HtmlHelper.GenerateLink( ControllerContext.RequestContext, RouteTable.Routes, "Edit", "Default", "EditPast", "CreateLog", new RouteValueDictionary(new { id = duplicateLogs.First().LogId }), buttonAttributes); return Json(new { Status = ImportStatus.Duplicate.ToString(), Message = "This log has been previously entered", //Action = link }, JsonRequestBehavior.AllowGet); } // verify vehicle exists if (log.Vehicle == null) { return Json(new { Status = ImportStatus.Failure.ToString(), Message = "Vehile with supplied ID does not exist", Action = GetFixLink(viewModel) }, JsonRequestBehavior.AllowGet); } // verify city exists if (DataService.FindCityByName(log.CityName) == null) { return Json(new { Status = ImportStatus.Failure.ToString(), Message = "City must exist in system", Action = GetFixLink(viewModel) }, JsonRequestBehavior.AllowGet); } // SAVE IT! DataService.AddLog(log); var successLink = HtmlHelper.GenerateLink( ControllerContext.RequestContext, RouteTable.Routes, "Edit", "Default", "EditPast", "CreateLog", new RouteValueDictionary(new { id = log.LogId }), buttonAttributes); return Json(new { Status = ImportStatus.Success.ToString(), Action = successLink }, JsonRequestBehavior.AllowGet); } catch (DbEntityValidationException ex) { // Retrieve the error messages as a list of strings. var errorMessages = ex.EntityValidationErrors .SelectMany(x => x.ValidationErrors) .Select(x => x.ErrorMessage); // Join the list to a single string. var fullErrorMessage = string.Join(", ", errorMessages); return Json(new { Status = ImportStatus.Failure.ToString(), Message = fullErrorMessage, Action = GetFixLink(viewModel) }, JsonRequestBehavior.AllowGet); } catch (Exception ex) { var message = ex.Message; return Json(new { Status = ImportStatus.Failure.ToString(), Message = message, Action = GetFixLink(viewModel) }, JsonRequestBehavior.AllowGet); } } private string GetFixLink(ImportLogViewModel viewModel) { try { viewModel.GetCreateLogViewModel(); } catch { return string.Empty; } return RenderRazorViewToString("ImportFix", viewModel); } [HttpPost] public ActionResult ImportFix(ImportLogViewModel viewModel) { var createGetLogViewModel = viewModel.GetCreateLogViewModel(); createGetLogViewModel.Purpose = new SelectListViewModel { Available = GetPurposeTypesSelectList() }; return View("Index", createGetLogViewModel); } public ActionResult ImportTemplate() { var template = LogImportTemplateWriter.Write(); return File(template, "application/ms-excel", "MileageTraker_ImportTemplate.xls"); } #endregion } }