Search code examples
c#jqueryasp.net-corerazor-pagesabp-framework

ABP framework - Best way to ValidateModel() and show success message


Context: Web application developed with ASPNet Core over ABP 2.9 framework (Razor pages).

I need to validate a model (it implements Validate(...) from IValidatableObject and calls the application service to perform some validations), then call an application service, and finally show a success message (with the same look & feel as abp.notify.success(...)).

Purpose of this post: To validate whether I am following the best practices or doing things in the correct way with ABP framework. If so, there are some suggestions to ABP team.

What I've tried:

1.- First, I tried submitting the form, but I didn't find an easy way to show the success message (like abp.notify.success ones) from the server method: public virtual async Task<IActionResult> OnPostAsync().

It would be nice to have a simple way to send client messages (like abp.notify.success ones) from server side. Maybe there is a way and I didn't find it.

2.- Second, I tried to cancel form submission and peform validation in client side, call the application service and show the message, also from client side. The issue here is that validations on public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) method were not executed from client side calling form.valid().

Possible improvement to ABP framework would be to enable an easy way to perform same server DataValidation() from client side. Maybe it exists and I didn't find it.

3.- Finally, I did the following:

a) Server side: to perform ValidateModel() and call the application service (see cshtml.cs code).

b) Client Side: avoid form submission and submit it with ajax, and finally show the success message with abp.notify.success(...)) (see javascript code).


Here are the questions related to previous issues. I appreaciate your comments or suggestions:

1.- Is there any better way to perform this scenario using ABP framework utils?

2.- Am I following the best practices? (placing the classes and logic in the correct layers)

  • DTO with data annotations in Application.Contracts layer.
  • DTOValidator class that inherits from DTO and IValidatableObject and implements Validate(...) method in Application.Contracts layer. This is to keep simple DTOs between client and application services.
  • Model class that inherits from DTOValidator and is binded to form in .cshtml.cs (Example: public class IndexPolicies : UpdatePolicyDtoValidator {})

Solution

  • Dealing with another issue I have found a solution that solves the problem taking full advantage of the ABP framework::

    a) Server side: to perform ValidateModel() and call the application service (same as described on my third try).

    b) Client Side: to use a simple button instead of submit one and call abpAjaxForm(options) with abp.notify.success() on success function. Then submit the form:

    var _defaultPoliciesForm = $("#DefaultPoliciesForm");
    var _saveButton = $("#SaveButton"); 
    
    _saveButton.click(function (e) {
        var options = {
            beforeSubmit: function (arr, form) {
                _saveButton.buttonBusy(true);
            },
            success: function (responseText, statusText, xhr, form) {
                abp.notify.success(l("UpdatedSuccessfully"));
            },
            complete: function (jqXhr, status, form) {
                _saveButton.buttonBusy(false);
            }
        }
        _defaultPoliciesForm.abpAjaxForm(options);
        _defaultPoliciesForm.submit();
    });
    

    Hope it can be useful to others with the same issue. Anyway, I remember my suggestions to ABP team:

    • Ability to send client messages like abp.notify.success(...) ones from server side.

    • Ability to perform same server validation as DataValidation() from client side