nopSolutions / nopCommerce

ASP.NET Core eCommerce software. nopCommerce is a free and open-source shopping cart.
https://www.nopcommerce.com
Other
9.31k stars 5.32k forks source link

Fluent validation not registered for plugins where plugin name does not begin with Nop. #3960

Closed davidandrewpowell closed 4 years ago

davidandrewpowell commented 5 years ago

nopCommerce version: 4.20

NopCommerce 4.20 appears to allow plugins with any name to be installed.

In InstallController.Index(InstallModel) the application looks for plugins that implement the IPlugin interface:

var plugins = pluginService.GetPluginDescriptors<IPlugin>(LoadPluginsMode.All)
    ...

and then prepares these plugins for installation.

So, for example, this would allow me to register plugins with the following naming structure: "CompanyName.Plugin.Group.Name"

However, in the Nop.Web.Framework/Infrastructure/Extensions/ServiceCollectionExtensions.cs AddNopMvc() method, there is the following code to register fluent validation:

//add fluent validation
mvcBuilder.AddFluentValidation(configuration =>
{
    //register all available validators from Nop assemblies
    var assemblies = mvcBuilder.PartManager.ApplicationParts
        .OfType<AssemblyPart>()
        .Where(part => part.Name.StartsWith("Nop", StringComparison.InvariantCultureIgnoreCase))
        .Select(part => part.Assembly);
    configuration.RegisterValidatorsFromAssemblies(assemblies);

    //implicit/automatic validation of child properties
    configuration.ImplicitlyValidateChildProperties = true;
});

Note the line:

.Where(part => part.Name.StartsWith("Nop", StringComparison.InvariantCultureIgnoreCase))

which only registers fluent validation from plugins with names starting with Nop. So only plugins with the naming structure "Nop.Plugin.Group.Name" with have the fluent validation registered.

If I have understood this correctly then there appears to be a mistake here.

Either:

Plugins of any name should be allowed to be registered and therefore the the validation from those plugins should be registered also.

Or:

Only plugins starting with Nop. should be registered and therefore the current validation registration is correct.

My understanding is that plugins with any name should be registered and therefore the validation registration should be changed to match.

See also: https://www.nopcommerce.com/boards/t/67488/nopcommerce-42-validation-is-not-working-while-plugin-assembly-is-not-start-with-nop.aspx#238089

alinmircea commented 4 years ago

There is a simple workaround for this, to register validators in the Plugin startup

services.AddTransient<IValidator<Model>, ModelValidator>();

AndreiMaz commented 4 years ago

Thanks. But after some consideration we've decided not to implement this functionality

markusschnepf commented 3 months ago

There is a simple workaround for this, to register validators in the Plugin startup

services.AddTransient<IValidator<Model>, ModelValidator>();

seems that this does not work for models that are in another assemly/project. I tried to add a validator for property "VatNumber" in the model "RegistrationModel", used by the "CustomerController" in the "Register" action.

I've overwritten the "Register.cshtml", added the <nop-required /> tag and the <span asp-validation-for="VatNumber"></span>, added a "ViewLocationExpander" and a validation class: public class MyRegisterValidator2 : BaseNopValidator<RegisterModel> { public MyRegisterValidator2(ILocalizationService localizationService, IStateProvinceService stateProvinceService, CustomerSettings customerSettings) { RuleFor(x => x.VatNumber).NotEmpty().WithMessage("VAT number is required!"); } }

of course I've put services.AddTransient<IValidator<RegisterModel>, MyRegisterValidator2>(); in my PluginNopStartup's method "ConfigureServices"

but the validation does not work.

when I put the "RuleFor" in "nop.web --> validators --> customer --> RegisterValidator" it works perfectly fine. but not, when I register the validator from within my plugin project.

it does not matter if i create a new unique class (like "MyRegisterValidator2") or if I create a new partial class RegisterValidator (same name as in nop.web).