Walkthrough Generated Code Update

BasicCRUD Part 2

Now let us walk through the generated code for the update and come back to our solution.

The first thing is the input API model. Keeping a separate input api model is very handy in maintaining the fields for update and keeping the unwanted fields out of the flow.

public class UpdateCustomerInputAPIModel : IFlexInputAPIModel
{
[StringLength(32)]
public string Id { get; set; }
[StringLength(50)]
public string Name { get; set; }
}

Let’s now see the update customer.

public partial class CustomerController : FlexControllerBridge
{
[HttpPut]
[Route("UpdateCustomer")]
[ProducesResponseType(typeof(BadRequestResult), 400)]
[ProducesResponseType(typeof(string), 200)]
public async Task<IActionResult> UpdateCustomer([FromBody]UpdateCustomerInputAPIModel value)
{
if (value == null)
{
ModelState.AddModelError("requesterror", $"{nameof(UpdateCustomerInputAPIModel)} can not be empty");
_logger.LogDebug($"{nameof(UpdateCustomerInputAPIModel)} can not be empty" + DateTime.Now.ToString());
return ControllerContext.ReturnFlexBadRequestError();
}
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
CommandResult cmdResult = null;
UpdateCustomerParams updateParams = new UpdateCustomerParams();
FlexHostContextInfoBridge hostContextInfo = new FlexHostContextInfoBridge();
hostContextInfo.Populate<IFlexHostHttpContextAccesorBridge>(_appHttpContextAccessor);
updateParams.HostContextInfo = hostContextInfo;
updateParams.Model = value;
cmdResult = await ProcessCustomerService.UpdateCustomer(updateParams);
if (cmdResult.Status != Status.Success)
{
ModelState.ComposeFlexBadRequestError(cmdResult.Errors());
return ControllerContext.ReturnFlexBadRequestError();
}
return Ok(cmdResult.result);
}
}

The input is received in the action. We have the HTTP PUT automatically configured for the update customer. Action functions as it was explained in the POST in earlier section.

Lets look at the Services layer.

Here all the plugins are executed for the validations.

public partial class ProcessCustomerService : IProcessCustomerService
{
/// <summary>
/// YourRemarksForMethod
/// </summary>
/// <param name="param"></param>
/// <returns></returns>
public async Task<CommandResult> UpdateCustomer(UpdateCustomerParams param)
{
UpdateCustomerDataPacket packet = _flexHost.GetFlexiFlowDataPacket<UpdateCustomerDataPacket>();
packet.InputParams = param;
try
{
FlexiBusinessRuleSequenceBase<UpdateCustomerDataPacket> sequence = _flexHost.GetFlexiBusinessRuleSequence<UpdateCustomerSequence, UpdateCustomerDataPacket>();
await FlexiBusinessRule.Run(sequence, packet);
}
catch (FlexiFlowAbnormalTerminationException ex)
{
packet.AddError("requesterror", ex);
return new CommandResult(Status.Failed, packet.Errors());
}
if (packet.HasError)
{
return new CommandResult(Status.Failed, packet.Errors());
}
else
{
UpdateCustomerCommand cmd = new UpdateCustomerCommand
{
model = param.Model,
HostContextInfo = param.HostContextInfo
};
await ProcessCommand(cmd);
CommandResult cmdResult = new CommandResult(Status.Success);
UpdateCustomerResultModel outputResult = new UpdateCustomerResultModel();
cmdResult.result = outputResult;
return cmdResult;
}
}
}
public class UpdateCustomerResultModel : FlexOutputAPIModelForUpdate
{
}
public partial class ProcessCustomerService : IProcessCustomerService
{
private async Task ProcessCommand(UpdateCustomerCommand cmd)
{
await _bus.Send(cmd);
}
}

Here if it is non eventual the command is sent to the bus. The bus receives the command update customer Handler and executes the plugin for the Post bus so we go to the plug-in.

Update customer plugin. So here the flow is the same as your insert. All validations follow the same process. So this is the method in the domain model and the rest of the things Remains the Same insert or update model.

Let us look at the update customer model.

public partial class Customer : DomainModelBridge
{
public virtual Customer UpdateCustomer(UpdateCustomerCommand cmd)
{
Guard.AgainstNull("Customer model cannot be empty", cmd);
this.Convert(cmd.model);
this.LastModifiedBy = cmd.HostContextInfo.UserId;
//Map any other field not handled by Automapper config
this.SetModified();
//Set your appropriate SetModified for the inner object here
return this;
}
}

Now we'll go to the mapper and see what we have done, there is no domain in the mapper.

public CustomerMapperConfiguration() : base()
{
#region Input
CreateMap<UpdateCustomerInputAPIModel, Customer>();
#endregion
}

Once the update happens. The same way the event is raised here. On success and then it is further processed by subscribers or handlers.