0

I am asking this because after long time searching I haven't found a good answer on this yet...

Here is what I want:

Example: I have a domain model "JobPosting" which a user should be able to change state to published, if it is still a draft. Before publishing I must not only validate the model properties I must also validate many different requirements regarding the user account, it's registered company etc. All this validation logic is put into a service layer. So far so good...

This is how my service layer looks like:

public IValidationResult ValidatePublish(JobPosting jobPosting){
    ...
}

public void Publish(JobPosting jobPosting){
    jobPosting.State = JobPostingState.Published;
    ...
}

Any my controller:

public ActionResult Publish(PublishViewModel model){
    ...
    var validationResult = _jobService.ValidatePublish(jobPosting);
    if(validationResult.Success){
        _jobService.Publish(jobPosting);
        ...
    }
    ...
}

And here now my questions:

I want to be able to call the ValidatePublish from the controller to show validation errors in the view. However I must never be able to publish a job when validation fails. So to have my code more robust I added a second validation check in my Publish method in service layer:

public void Publish(JobPosting jobPosting){
    if(ValidatePublish(jobPosting).Success){
        jobPosting.State = JobPostingState.Published;
        ...
    }
}

but I have not such a good feeling with this approach because now I am calling the validation twice when validation is OK during each controller publish request.

What do you think. Is the second call to much? Is there a better approach? I am asking because my whole application looks like that and if I would ever forget a validation call in controller I might end up with an not allowed domain model state in database. That's why I added the second validation check in each service method.

Thanks in advance for your thoughts on this!!!

Simon
  • 171
  • 2
  • 11
  • "I am calling the validation twice " where are you calling the validation second time? – It's a trap Aug 26 '16 at 08:33
  • First call in controller: var validationResult = _jobService.ValidatePublish(jobPosting); Second time in service method Publish: if(ValidatePublish(jobPosting).Success){ – Simon Aug 26 '16 at 08:46
  • then why are you validating again in the method? You can just publish directly. – It's a trap Aug 26 '16 at 08:50

2 Answers2

1

One quick solution might be to have the Publisher class require the JobPosting and IValidationResult objects as arguments.

public void Publish(JobPosting jobPosting, IValidationResult validation)
{
    if (validation.IsValid)
    {
        jobPosting.State = JobPostingState.Published;
        // other work here...
    }
}

Your Controller can then call the Validator, receive an IValidationResult and pass that back to the presentation layer if needed. Otherwise pass on to Publisher

public ActionResult Publish(PublishViewModel model)
{
    var validationResult = _jobService.ValidatePublish(jobPosting);
    if(validationResult.Success) _jobService.Publish(jobPosting, validationResult);
    else return View("error", validationResult);
}

Edit:

A cleaner solution may be to have the Publisher class return a PublishAttempt result.

public class PublishAttempt : IValidationResult
{
    public enum AttemptOutcome {get; set;}
}

public ActionResult Publish(PublishViewModel model)
{
    var attempt = _jobService.Publish(jobPosting);
    if (attempt.Success) return View("success");
    else return View("error", attempt.ValidationResults);
}
Chima Osuji
  • 391
  • 2
  • 10
  • Thanks! Yes this would be also an approach... but what I don't like with it is that I could pass any validation result instance... could even just create a new empty one which is always valid. – Simon Aug 26 '16 at 08:56
  • Oh thanks :-) yes i like that... maybe I combine your idea with my last answer :-) just because I need the ability the call only the validation method... e.g. when I want to call the service validation via ajax to show errors in "realtime" – Simon Aug 26 '16 at 09:07
-1

The following just came into my mind... what do you think:

I change my service method to:

public IValidationResult Publish(JobPosting jobPosting, bool validateOnly = false){
    var validationResult = ValidatePublish(jobPosting);
    if(validateOnly) return validationResult;

    jobPosting.State = JobPostingState.Published;
    ...
    return validationResult;
}        

And then in controller I always call only the Publish method and not the extra ValidatePublish anymore:

public ActionResult Publish(PublishViewModel model)
{
    var validationResult = _jobService.Publish(jobPosting);
    if(!validationResult.Success) return View("error", validationResult);
}

And when I need only simple validation I do

var validationResult = _jobService.Publish(jobPosting, true);

Is this okey to do it like that? Or is it not good looking if a normal service call returns IValidationResult?

Simon
  • 171
  • 2
  • 11