0

I've created CreateAccountValidator class that is responsible for validating my binding model inside WebAPI2 application hosted on IIS.

Below is my class:

public class CreateAccountValidator : AbstractValidator<CreateAccountBindingModel>
{
    public CreateAccountValidator()
    {
        RuleFor(u => u.Amount)
            .Cascade(CascadeMode.StopOnFirstFailure)
            .GreaterThan(0).WithMessage("Must be greater than 0");

        RuleFor(u => u.FirstName)
            .Cascade(CascadeMode.StopOnFirstFailure)
            .NotEmpty().WithMessage("Name is required")
            .Length(3, 20).WithMessage("Name must be between 3 and 20 characters");

        RuleFor(u => u.LastName)
            .Cascade(CascadeMode.StopOnFirstFailure)
            .NotEmpty().WithMessage("Surname is required")
            .Length(3, 20).WithMessage("Surname must be between 3 and 20 characters");

        RuleFor(u => u.ID)
            .Cascade(CascadeMode.StopOnFirstFailure)
            .NotEmpty().WithMessage("ID is required")
            .Must(ValidateId).WithMessage("ID is invalid");
    }

    private bool ValidateId(CreateAccountBindingModel createAccountBindingModel, string id, PropertyValidatorContext context)
    {
        var id_valid = IdValidator.IsValid(id);
        if (!id_valid)
        {
            using (var db = new ApplicationDbContext())
            {
                //get request IP!!!
                db.SaveAlert(createAccountBindingModel.UserEmail, "ID - CHECKSUM", string.Format("User entered: {0}", id), "192.100.100.100");
                return false;
            }
        }
        return true;
    }
}

Inside ValidateId method I'm calling my custom validator, if it returns false I want to log that fact to database.

I need to get Request IP, but I don't know how can I do that. I don't have IOwinContext or Request properties. Inside Api Controllers I'm calling:

Request.GetOwinContext().Get<ApplicationDbContext>()

Can I access IOwinContext from classes inside my application? Is yes then how can I do that?

Misiu
  • 4,738
  • 21
  • 94
  • 198
  • I dont know if I would do database validation in the `FluentValidation`. That doesn't seem right. `FluentValidation` seems to me like just a set of simple guard clauses to make sure the user input is valid for use. Secondly, you DI should provide the OWIN context with the `DbContext`, so you can use that in a DI injected class. – Callum Linington Jul 19 '16 at 08:23
  • @CallumLinington I'm just using `app.CreatePerOwinContext(() => new ApplicationDbContext());` inside `Startup.cs` not fancy DI like ninject. I want to validate everything in one place and also log all errors that's why I'm using FluentValidation as shown in my question. So how can I access that OWIN context inside other classes? Do I must use DI system or can I do that without it? – Misiu Jul 19 '16 at 08:42
  • Do you do something like this `FluentValidationModelValidatorProvider.Configure(GlobalConfiguration.Configuration);` – Callum Linington Jul 19 '16 at 09:04
  • @CallumLinington something similar, inside `Configuration` method I'm calling: `HttpConfiguration config = new HttpConfiguration();//setting services and filtersFluentValidationModelValidatorProvider.Configure(config);` – Misiu Jul 19 '16 at 09:06
  • 1
    Isn't `HttpContext` a static in ASP.NET? – Callum Linington Jul 19 '16 at 09:40
  • @CallumLinington THANK YOU! Please post this as answer. I'm using http://stackoverflow.com/a/13249280/965722 to get IP and `var dbContext = HttpContext.Current.Request.GetOwinContext().Get();` to get ApplicationDbContext. If You have some other thoughts about those two please add them to answer as well. – Misiu Jul 19 '16 at 10:03
  • Done, but I really wouldn't do that, I would just stick with what you have got!! Your code is perfectly fine and sensible. – Callum Linington Jul 19 '16 at 10:15
  • @CallumLinington thank You, I've suggested small change in Your anser - Request is not needed, You can do `HttpContext.Current.GetOwinContext().Get();` – Misiu Jul 19 '16 at 10:22

1 Answers1

1

So HttpContext is static in ASP.NET.

So HttpContext.Current.Request.GetOwinContext()

However, you are using the ApplicationDbContext correctly in your question and I would not change it

Reason being, you want to only instantiate a new context around the smallest unit of work possible. That you have done absolutely correctly.

Callum Linington
  • 14,213
  • 12
  • 75
  • 154