/// <summary> /// This transfers error messages from the ValidationResult collection to the MVC modelState error dictionary. /// It looks for errors that have member names corresponding to the properties in the displayDto. /// This means that errors associated with a field on display will show next to the name. /// Other errors will be shown in the ValidationSummary /// </summary> /// <param name="status">The status that came back from the BizRunner</param> /// <param name="modelState">The MVC modelState to add errors to</param> /// <param name="displayDto">This is the Dto that will be used to display the error messages</param> public static void CopyErrorsToModelState <T>(this IBizActionStatus status, ModelStateDictionary modelState, T displayDto) { if (!status.HasErrors) { return; } var namesThatWeShouldInclude = PropertyNamesInDto(displayDto); foreach (var error in status.Errors) { if (!error.MemberNames.Any()) { modelState.AddModelError("", error.ErrorMessage); } else { foreach (var errorKeyName in error.MemberNames) { modelState.AddModelError( (namesThatWeShouldInclude.Any(x => x == errorKeyName) ? errorKeyName : ""), error.ErrorMessage); } } } }
public void SetupSecondaryDataIfRequired(object repository, IBizActionStatus status, object inputDto) { if (!IsDirectCopy) { //we need to call SetupSecondaryOutputData _dtoAccessInstance.SetupSecondaryData(repository, status, inputDto); } }
public T CreateDataWithPossibleSetup <T>(object repository, IBizActionStatus status, Action <T> runBeforeSetup) where T : class, new() { var result = new T(); runBeforeSetup?.Invoke(result); SetupSecondaryDataIfRequired(repository, status, result); return(result); }
protected internal override void SetupSecondaryData(DbContext db, IBizActionStatus status) { SetupSecondaryDataCalled = true; if (RaiseErrorInSetupSecondaryData) { status.AddError("Error in SetupSecondaryData"); } }
public async Task <T> CreateDataWithPossibleSetupAsync <T>(DbContext db, IBizActionStatus status, Action <T> runBeforeSetup) where T : class, new() { var result = new T(); runBeforeSetup?.Invoke(result); await SetupSecondaryDataIfRequiredAsync(db, status, result).ConfigureAwait(false); return(result); }
public Task <IActionResult> BizActionStatus(IBizActionStatus status, Func <Task <IActionResult> > getNormalActionResult) { if (status.HasErrors) { return(Task.FromResult(status.ToActionResult())); } return(getNormalActionResult()); }
/// <summary> /// This handled optional save to database with various validation and/or handlers /// Note: if it did save successfully to the database it alters the message /// </summary> /// <param name="db"></param> /// <param name="bizStatus"></param> /// <returns></returns> protected void SaveChangedIfRequiredAndNoErrors(DbContext db, IBizActionStatus bizStatus) { if (!bizStatus.HasErrors && RequiresSaveChanges) { bizStatus.CombineErrors(db.SaveChangesWithOptionalValidation( bizStatus.ShouldValidateSaveChanges(WrappedConfig.Config), WrappedConfig.Config)); WrappedConfig.Config.UpdateSuccessMessageOnGoodWrite(bizStatus, WrappedConfig.Config); } }
public IActionResult BizActionStatus(IBizActionStatus status, Func <IActionResult> getNormalActionResult) { if (status.HasErrors) { return(status.ToActionResult()); } return(getNormalActionResult()); }
/// <summary> /// This handled optional save to database with various validation and/or handlers /// Note: if it did save successfully to the database it alters the message /// </summary> /// <param name="db"></param> /// <param name="bizStatus"></param> /// <returns></returns> protected async Task SaveChangedIfRequiredAndNoErrorsAsync(DbContext db, IBizActionStatus bizStatus) { if (!bizStatus.HasErrors && RequiresSaveChanges) { bizStatus.CombineErrors(await db.SaveChangesWithOptionalValidationAsync( bizStatus.ShouldValidateSaveChanges(WrappedConfig.Config), WrappedConfig.Config) .ConfigureAwait(false)); WrappedConfig.Config.UpdateSuccessMessageOnGoodWrite(bizStatus, WrappedConfig.Config); } }
/// <summary> /// This copies errors for general display where we are not returning to a page with the fields on them /// </summary> /// <param name="status"></param> /// <param name="modelState"></param> public static void CopyErrorsToModelState(this IBizActionStatus status, ModelStateDictionary modelState) { if (!status.HasErrors) { return; } foreach (var error in status.Errors) { modelState.AddModelError("", error.ErrorMessage); } }
/// <summary> /// Inherit the errors of another <see cref="IBizActionStatus" /> /// </summary> /// <param name="status">The status that provides the errors</param> /// <returns>Return <see cref="BizActionStatus.HasErrors" /></returns> protected virtual bool InheritStatusFailed(IBizActionStatus status) { if (status.HasErrors) { foreach (var error in status.Errors) { AddValidationResult(error); } return(true); } return(false); }
/// <summary> /// This a) handled optional save to database and b) calling SetupSecondaryData if there are any errors /// It also makes sure that the runStatus is used at the primary return so that warnings are passed on. /// Note: if it did save successfully to the database it alters the message /// </summary> /// <param name="db"></param> /// <param name="bizStatus"></param> /// <returns></returns> protected void SaveChangedIfRequiredAndNoErrors(DbContext db, IBizActionStatus bizStatus) { if (!bizStatus.HasErrors && RequiresSaveChanges) { if (bizStatus.ValidateSaveChanges(Config)) { bizStatus.CombineErrors(db.SaveChangesWithValidation(Config)); } else { db.SaveChanges(); } Config.UpdateSuccessMessageOnGoodWrite(bizStatus, Config); } }
public static void UpdateSuccessMessageOnGoodWrite(IBizActionStatus bizStatus, IGenericBizRunnerConfig config) { if (bizStatus.HasErrors) { return; } if (bizStatus.Message != null && (bizStatus.Message == config.DefaultSuccessMessage || bizStatus.Message == StatusGenericHandler.ConstDefaultMessage)) { bizStatus.Message = config.DefaultSuccessAndWriteMessage; } else if (bizStatus.Message.LastOrDefault() != '.' && config.AppendToMessageOnGoodWriteToDb != null) { bizStatus.Message += config.AppendToMessageOnGoodWriteToDb; } }
/// <summary> /// This a) handled optional save to database and b) calling SetupSecondaryData if there are any errors /// It also makes sure that the runStatus is used at the primary return so that warnings are passed on. /// Note: if it did save successfully to the database it alters the message /// </summary> /// <param name="db"></param> /// <param name="bizStatus"></param> /// <returns></returns> protected async Task SaveChangedIfRequiredAndNoErrorsAsync(DbContext db, IBizActionStatus bizStatus) { if (!bizStatus.HasErrors && RequiresSaveChanges) { if (bizStatus.ValidateSaveChanges(Config)) { bizStatus.AddValidationResults(await db.SaveChangesWithValidationAsync()); } else { await db.SaveChangesAsync().ConfigureAwait(false); } Config.UpdateSuccessMessageOnGoodWrite(bizStatus); } }
/// <summary> /// This updates the message on a successful write /// </summary> /// <param name="bizStatus"></param> public void UpdateSuccessMessageOnGoodWrite(IBizActionStatus bizStatus) { if (bizStatus.HasErrors) { return; } if (bizStatus.Message != null && bizStatus.Message == DefaultSuccessMessage) { bizStatus.Message = DefaultSuccessAndWriteMessage; } else if (bizStatus.Message.LastOrDefault() != '.' && AppendToMessageOnGoodWriteToDb != null) { bizStatus.Message += AppendToMessageOnGoodWriteToDb; } }
public async Task SetupSecondaryDataIfRequiredAsync(object repository, IBizActionStatus status, object inputDto) { //NOTE: Async business methods can use either sync or async dto, so we need to handle both if (!IsDirectCopy) { //we need to call SetupSecondaryOutputData if (_isAsync) { await _dtoAccessInstance.SetupSecondaryDataAsync(repository, status, inputDto).ConfigureAwait(false); } else { _dtoAccessInstance.SetupSecondaryData(repository, status, inputDto); } } }
/// <summary> /// On succeed, returns an <see cref="OkResult"/>, else return a failed response with the error messages. /// </summary> /// <param name="status">The business action status</param> public static IActionResult ToActionResult(this IBizActionStatus status) { if (!status.HasErrors) { return(new OkResult()); } var errors = status.Errors.OfType <RestErrorValidationResult>().Select(x => x.Error).ToArray(); var firstError = errors.FirstOrDefault(); var httpCode = firstError == null ? StatusCodes.Status400BadRequest : (int)ErrorTypes.ErrorStatusCodes[firstError.Type]; return(new JsonResult(errors) { StatusCode = httpCode }); }
/// <summary> /// This handled optional save to database with various validation and/or handlers /// Note: if it did save successfully to the database it alters the message /// Note: Only be used if type of DbContext is being used and supplied via IRepository /// </summary> /// <param name="repository"></param> /// <param name="bizStatus"></param> /// <returns></returns> protected void SaveChangedIfRequiredAndNoErrors(object repository, IBizActionStatus bizStatus) { if (repository.GetType().IsSubclassOf(typeof(DbContext))) { try { DbContext db = (DbContext)repository; if (!bizStatus.HasErrors && RequiresSaveChanges && db != null) { bizStatus.CombineStatuses(db.SaveChangesWithOptionalValidation( bizStatus.ShouldValidateSaveChanges(WrappedConfig.Config), WrappedConfig.Config)); WrappedConfig.Config.UpdateSuccessMessageOnGoodWrite(bizStatus, WrappedConfig.Config); } } catch (Exception) { throw; } } }
/// <summary> /// This is called by the BizRunner’s GetOriginal or ResetDto methods. /// It sets up the presentation layer properties /// </summary> /// <param name="db">The DbContext to allow access to the database</param> /// <param name="status">The BizActionStatus so you can register errors</param> protected override void SetupSecondaryData(DbContext db, IBizActionStatus status) { if (OrderId == 0) { throw new InvalidOperationException("You must set the OrderId before you call SetupSecondaryData"); } if (UserId == null) { throw new InvalidOperationException("You must set the UserId before you call SetupSecondaryData"); } var order = db.Set <Order>() .Include(x => x.LineItems).ThenInclude(x => x.ChosenBook) .SingleOrDefault(x => x.OrderId == OrderId); if (order == null) { status.AddError("Sorry, I could not find the order you asked for."); HasErrors = true; //Log possible hacking return; } DateOrderedUtc = order.DateOrderedUtc; OriginalDeliveryDate = order.ExpectedDeliveryDate; NewDeliveryDate = OriginalDeliveryDate < DateTime.Today ? DateTime.Today : OriginalDeliveryDate; BookTitles = order.LineItems.Select(x => x.ChosenBook.Title).ToList(); PossibleDeliveryDates = new SelectList(FormPossibleDeliveryDates(DateTime.Today)); var selected = PossibleDeliveryDates.FirstOrDefault(x => x.Text == NewDeliveryDate.ToString("d")); if (selected != null) { selected.Selected = true; } }
public void SetupSecondaryData(DbContext db, IBizActionStatus status, object dto) { ((TDtoIn)dto).SetupSecondaryData(db, status); }
protected internal override async Task SetupSecondaryDataAsync(object repository, IBizActionStatus status) { SetupSecondaryDataCalled = true; if (RaiseErrorInSetupSecondaryData) { status.AddError("Error in SetupSecondaryData"); } }
/// <summary> /// Use this to setup any extra data needed when showing the dto to the user for input, e.g. supporting dropdownlists /// This is called a) when a dto is created by GetDto , b) when ResetDto is called and c) when the call to the business logic fails /// </summary> /// <param name="db"></param> /// <param name="status">You can raise an error, which will stop the biz logic from running</param> protected internal virtual void SetupSecondaryData(DbContext db, IBizActionStatus status) { }
public void SetupSecondaryData(object repository, IBizActionStatus status, object dto) { ((TDtoIn)dto).SetupSecondaryData(repository, status); }
public async Task SetupSecondaryDataAsync(object repository, IBizActionStatus status, object dto) { await((TDtoIn)dto).SetupSecondaryDataAsync(repository, status).ConfigureAwait(false); }
// Async method lacks 'await' operators and will run synchronously /// <summary> /// Use this to setup any extra data needed when showing the dto to the user for input, e.g. supporting dropdownlists /// This is called a) when a dto is created by GetDto , b) when ResetDto is called and c) when the call to the business logic fails /// </summary> /// <param name="db"></param> /// <param name="status">You can raise an error, which will stop the biz logic from running</param> /// <returns></returns> #pragma warning disable CS1998 protected internal virtual async Task SetupSecondaryDataAsync(DbContext db, IBizActionStatus status) #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously { }
public async Task SetupSecondaryDataAsync(DbContext db, IBizActionStatus status, object dto) { await((TDtoIn)dto).SetupSecondaryDataAsync(db, status).ConfigureAwait(false); }
public IActionResult BizActionStatus(IBizActionStatus status) { return(status.ToActionResult()); }