This article highlights a pattern which is used to return an appropriate validation outcome based on the output of the stored procedure doing the business rule validations.
Scenario
In an ASP.NET Web Application Project, we often have requirements to do some validations in the stored procedures and return an appropriate message to the front-end. Further actions will be made based on the validation result.
Validation Response
To address the above scenario, I prefer to have an Interface based validation response being returned from the DAL layer to the consuming code.
The code for the desired Interface is as follows,
- public interface IResponse
- {
- bool Success { get; set; }
- string Message { get; set; }
- }
Next is we can have our own custom class as shown below which will inherit this interface for doing a specific validation.
- public class ValidationResponse : IResponse
- {
- bool Success { get; set; }
- string Message { get; set; }
- }
When the validation results in the expected outcome, Success boolean property is set to true and the Message will have a standard message for eg., "SUCCESS".
However, if the validation fails as per our logic or any exception is thrown, then Success is set to false and Message will have the desired validation message which will be displayed to the user.
The API in the DAL layer would have the return type as IResponse which gives us the flexibility to return any type of class implementing the interface.
- public IResponse DoSomeValidation()
- {
-
- }
This pattern would help us in creating a decoupled method in the DAL layer and have an appropriate response. Let's see a real-time example.
Requirement is to validate the password update activity by passing the current password and new password hash as inputs to the stored procedure and return the validation response.
- public IResponse ValidatePasswordUpdate(string oldPwdHash, string newPwdHash, string userName) {
- IResponse validationResponse;
- try {
- using(var sqlCon = new SqlConnection(Helper.ConnectionString))
- using(var cmd = CreateCommand(CommandType.StoredProcedure, "Admin_spValidatePasswordUpdate")) {
- cmd.Connection = sqlCon;
- cmd.Parameters.Add(new SqlParameter("@OldPwdHash", oldPwdHash));
- cmd.Parameters.Add(new SqlParameter("@NewPwdHash", newPwdHash));
- cmd.Parameters.Add(new SqlParameter("@userName", userName));
- if (sqlCon != null) sqlCon.Open();
- var reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
- validationResponse = new ValidationResponse();
- if (reader != null && reader.HasRows) {
- if (reader.Read() && reader["Result"] != DBNull.Value) {
- validationResponse.Message = reader["Result"].ToString();
- validationResponse.Success = validationResponse.Message.Equals(Constants.SuccessMsg, StringComparison.OrdinalIgnoreCase);
- } else validationResponse.Success = false;
- } else validationResponse.Success = false;
- }
- } catch (Exception ex) {
- if (validationResponse == null) validationResponse = new ValidationResonse();
- validationResponse.Success = false;
- validationResponse.Message = "Password update attempt is not successful due to a technical error";
- } finally {
- return validationResponse;
- }
- }
ValidatePasswordUpdate method will get the desired validation message as output from the stored procedure and returns an object of type IResponse. In future, if we need to transfer additional data as part of IResponse object, we could create a new class with required properties specific to the context.
We can consume this response object in the code-behind file or AJAX code and based on the object values, we could enable/disable the next actions as per the business rule.