1

I am developing Web Applications using ASP.Net MVC 5 (.net framework), now trying develop my next Project using .NET Core 3.1 with Entity framework Core (with Code first approach).

I am trying separate business logic in a separate Wrapper class like:

public interface IValidationDictionary
{
    void AddError(string key, string errorMessage);
    bool IsValid { get; }
}

public class ModelStateWrapper : IValidationDictionary
{
    private ModelStateDictionary _modelState;

    public ModelStateWrapper(ModelStateDictionary modelState)
    {
        _modelState = modelState;
    }

    #region IValidationDictionary Members

    public void AddError(string key, string errorMessage)
    {
        _modelState.AddModelError(key, errorMessage);
    }

    public bool IsValid
    {
        get { return _modelState.IsValid; }
    }
    #endregion
}

In the EmployeeRepo class:

    private Models.IValidationDictionary _modelState;
    public EmployeeRepo(Models.IValidationDictionary modelState)
    {
        _modelState = modelState;
    }

   public int Create(Models.Employee ObjToCreate)
   {
        if (!Validate(ObjToCreate))
            return 0;

        _context.Employee.Add(ObjToCreate);
        _context.SaveChanges();

        return ObjToCreate.Id;
   }

    protected bool Validate(Models.Employee objToValidate)
    {
        if (objToValidate.Name.Trim().Length == 0)
            _modelState.AddError("Name", "Name is required.");

        if (null == objToValidate.DOB)
            _modelState.AddError("DOB", "DOB is required");
        return _modelState.IsValid;
    }

In the Controller:

private Repository.IEmployeeRepo repo;
public EmployeesController(ApplicationDbContext context)
{
    _context = context;
    repo = new Repository.EmployeeRepo(new Models.ModelStateWrapper(this.ModelState));
}

    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult Create([Bind("Name,DOB,Department")] Employee employee)
    {
        var respId = repo.Create(employee);
        if (0 != respId.Id)
        {
            return RedirectToAction(nameof(Details), new { id = respId.Id });
        }
        return View(employee);
    }

I am expecting ModelState errors to be update in the controller which is added by the wrapper class, but model validation error not updating in the Controller.

Thanks for your time and for any response.

With Best Regards, Raju Mukherjee

raju1208
  • 95
  • 7
  • I suggest that you add a breakpoint in the `Create` method to test, confirm whether the employee receives the corresponding data, and then confirm which piece of code is the problem, and I can't see how you call `_context ` in your custom Create method. – LouraQ Jun 02 '20 at 09:36
  • @YongqingYu During debugging inspection I found Validate() method of EmployeeRepo is added model error for null DOB and ModelState.IsValid also False as intended, but when it revert back with 0 to Controller still ModelState is not updated i.e. ModelState.IsValid is True and error added by EmployeeRepo is not available to show in the View. For the _context I removed Code for the timing as I found error during DbContext object creation at Repo class as this portion is managed by DI which configured in the Startup.cs class in CORE MVC...Thanks – raju1208 Jun 02 '20 at 15:42
  • You mentioned that the error cannot be displayed in the view, so please provide your view code for our reference, and the Create method finally returns an int type, i think respId.Id is wrong. – LouraQ Jun 03 '20 at 02:30
  • @YongqingYu as mentioned Model Error added in the Repository is not reflecting in the Controller therefor not able to appear to user view. (respId.Id is wrong, once I return Employee object type from Create, pls ignore it) View Code for your reference: '
    '
    – raju1208 Jun 03 '20 at 12:57

1 Answers1

0

You just want to use a custom verification method to verify these two fields, right?

The method you wrote is too complicated.

To bind the corresponding error message, you need to add your custom verification attribute above the corresponding fields like [Required].

In fact, you only need to inherit the ValidationAttribute method and rewrite the IsValid method.

    public class Employee
    { 
        public int Id { get; set; }

        [CustomValidate]
        public string Name { get; set; }

        [CustomValidate]
        public string DOB { get; set; }

        public string Department{ get; set; }
    }

Custom Method:

 public class CustomValidateAttribute : ValidationAttribute
    {
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (value == null || string.IsNullOrEmpty(value.ToString().Trim()))
            {
                return new ValidationResult(validationContext.DisplayName + " is required.");
            }

            return ValidationResult.Success;
        }
    }

Create:

 [HttpPost]
        public IActionResult Create([Bind("Name,DOB,Department")]Employee employee)
        { 
            if (ModelState.IsValid)
            {
                _context.Employee.Add(employee); 
                _context.SaveChanges();
                return RedirectToAction(nameof(Details), new { id = employee.Id });
            }
            return View(employee);
        }

Here is the test result:

enter image description here

LouraQ
  • 6,443
  • 2
  • 6
  • 16
  • Please refer the subject, I am actually trying to give responsibility to Repository class for business logic validation (same as Service Layer or BLL do). Just to validate few fields using data annotation or Custom validation is not purpose of this POC project: If I add Code like ' if (null == employee.DOB) ModelState.AddModelError("DOB", "Date of birth is required");' in the Controller Post Create method I get ModelState.IsValid FALSE with model validation error if DOB field is null supplied, wrote the same in Repository class and expecting the same result. – raju1208 Jun 04 '20 at 06:39
  • Please suggest if you have any simple solution to accomplish the same, the code is working fine for years with ASP.Net MVC 5 in .NetFramework 4.5 – raju1208 Jun 04 '20 at 06:44
  • @raju1208, If you must display the error message based on the method you provide, I suggest that you can use `jquery ajax` to call the Create action, and then add the corresponding message to the success method of ajax through the content returned by the action, can you accept this plan? If possible, I will update my post. – LouraQ Jun 04 '20 at 09:03
  • For large projects this will not work, anyhow appear error message is not the goal, the matter is to develop application with good practice so that maintenance and enhancement get easy in future. – raju1208 Jun 04 '20 at 17:08