Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/build error type response #12

Closed
wants to merge 3 commits into from

Conversation

Wellingtonbsjr
Copy link

Summary

Create method WithRuleType in validation, to override property name with Prefix and Type.

How to use method WithRuleType in validation?

RuleFor(x => x.Text)
                .NotEmpty()
                .WithMessage("Text can't be null")
                .WithRuleType("SOME_RULE");

How property name stay?

{Prefix}.{RuleType}.{PropertyName}
_RuleType.SOME_RULE.Text

Why use it?
To identify Rules in InvalidModelStateResponseFactory and customize the HTTP response.

public static class MvcBuilderExtensions
{
    private const string PropertyDefault = "msg";

    /// <summary>
    /// Configure the custom bad request response format for all validation errors (model binding and ModelValidationFilter).
    /// </summary>
    /// <param name="builder"></param>
    /// <returns></returns>
    public static IMvcBuilder ConfigureValidationResponseFormat(this IMvcBuilder builder)
    {
        builder.ConfigureApiBehaviorOptions(options =>
        {
            options.InvalidModelStateResponseFactory = context =>
            {
                var response = new ErrorResponse
                {
                    Error = new Dictionary<string, string[]>(),
                    Type = GetRuleType(context)
                };

                foreach (var (key, value) in context.ModelState.Where(x => x.Value.Errors.Any()))
                {
                    var errorMessage = value.Errors.Select(e => e.ErrorMessage).ToArray();
                    var errorKey = key.Contains(RuleTypeConst.Prefix) ? PropertyDefault : key;
                    response.Error.Add(errorKey, errorMessage);
                }

                return new BadRequestObjectResult(response);
            };
        });

        return builder;
    }

    private static string GetRuleType(ActionContext context)
    {
        var type = "ERROR_DEFAULT";

        var errorType = context.ModelState.LastOrDefault(error => error.Key.Contains(RuleTypeConst.Prefix));

        if (!string.IsNullOrEmpty(errorType.Key))
            type = GetRuleType(errorType.Key);

        return type;
    }

    private static string GetRuleType(string key) =>
        key.Split('.')[1];
}

@sonarqubecloud
Copy link

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

100.0% 100.0% Coverage
0.0% 0.0% Duplication

/// <summary>
/// Prefix used to override property name.
/// </summary>
public const string Prefix = "_RuleType";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: maybe I'm missing something here, but is this prefix really required?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@luizhlelis this prefix is important to set correctly type in response.
We only set type, if exists an internal ErrorCode with this prefix.

if (!string.IsNullOrEmpty(propertyName))
options.WithName(propertyName);

options.WithErrorCode($"{RuleTypeConst.Prefix}.{type}");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thought: we're gonna need to use the same extension method WithErrorCode in #8, but I think we can use it in both scenarios. We can set some predefined words as ErrorCodes to change the response status code.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice @luizhlelis, make sense.
We can use a new Enum.ErrorsStatusCode in this lib, creating a new method like "WithStatusCode(Enum.ErrorsStatusCode)".

@Wellingtonbsjr Wellingtonbsjr changed the base branch from main to feature/customer-main November 1, 2022 23:13
@Wellingtonbsjr Wellingtonbsjr changed the base branch from feature/customer-main to main November 1, 2022 23:13
@Wellingtonbsjr
Copy link
Author

We create other branch feature/customer-main, to follow this:
1 - Change lib to response Bad Request with the format defined in the ower playbook.

{
    "error": {
        "Cnpj": [
            "O CNPJ do cliente deve ter 14 caracteres"
        ]
    },
    "type": "VALIDATION_ERRORS"
}

2 - Apply branch feature/customer-main in customer project;
3 - Later apply these changes to the branch main.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants