Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Repository Pattern - Validating Object and Return Message

I'm working on a website, and just trying to get my head around the general structure. I have a database in the background that I'm accessing using the "Repository Pattern". I have the below code in my UserRepository class:

public bool IsValid(User user)
{
  if (_context.Users.Any(c => c.EmailAddress == user.EmailAddress))
  {
    Message = "Email address already in use";
    return false;
  }

  return true;
}

And that is implemented here

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(User user)
{
  if (ModelState.IsValid)
  {
    var context = new Context("DatabaseContext");
    var userRepo = new UserRepository(context);

    if (userRepo.IsValid(user))
    {
      userRepo.Add(user);
      // return to different view
    }
    else
    {
      // display userRepo.Message on page
      return View(user);
    }
  }

  return View(user);
}

My problem is I don't think I'm going around the "message" bit correctly, but I can't find anything online to help me out (specifically around repository). I think I should be changing the return type of IsValid to something like a result (as I've seen with dialog boxes), but again, I'm not sure.

Any help would be much appreciated.

Thanks.

like image 851
Oyyou Avatar asked Jun 06 '17 08:06

Oyyou


People also ask

What is repository pattern in Java with example?

In this article, we will learn what is Repository pattern and how to implement the Repository pattern in Java with an example. Repository layer is added between the domain and data mapping layers to isolate domain objects from details of the database access code and to minimize scattering and duplication of query code.

What happens before and after the repository pattern?

Before and after the Repository pattern shows a little preview of what we’re going to build: a Repository object that sits between our domain model and the database. Figure 1. Before and after the Repository pattern The code for this chapter is in the chapter_02_repository branch on GitHub.

Does the repository pattern apply to a domain model?

A question that arose when we discussed the Repository Pattern is about its application in a domain model that has lots and lots of objects - let's say, a hundred, to put a number. Since you named the class AbstractRepository, and not AbstractBatchRepository, I'm guessing that you'll have a single repository class for the entire application.

What is the difference between queries and repository pattern?

Queries (in CQS) are used to return information to the user interface while the repository pattern is used to create an abstraction layer which can be used in your business code.


2 Answers

One way to achieve this is exactly like you have suggested - change the return type of IsValid.

In the past I have had similar validation methods in my "business layer" that return a collection of ValidationResult, where each returned record accounts for a validation error within the model and an empty collection would be interpreted as a valid model.

For example:

public class ValidationResult
{
    public string FieldName { get; set; }
    public string Message { get; set; }
}

public interface IValidator<T>
{
    IEnumerable<ValidationResult> IsValid(T model);
}

//...in your implementation
public IEnumerable<ValidationResult> IsValid(User user)
{
    //Return a new ValidationResult per validation error
    if (_context.Users.Any(c => c.EmailAddress == user.EmailAddress))
    {
        yield return new ValidationResult
        {
            Message = "Email address already in use",
            FieldName = nameof(user.EmailAddress)
        };
    }
}

This could then be interpreted by your presentation layer to feedback to the user.

like image 88
Oliver Avatar answered Oct 13 '22 20:10

Oliver


I agree with what you mentioned in question. Returning custom class will be better approach IMO.

public ValidationResult IsValid(User user)
{
  ValidationResult validationResult = new ValidationResult(true, "");
  if (_context.Users.Any(c => c.EmailAddress == user.EmailAddress))
  {
    validationResult.Status = false;
    validationResult.Message = "Email address already in use";
    return validationResult;
  }

  return validationResult;
}

This way, Status and Message give you all info needed. Check the status first. If it is false, check message for exact details.

like image 3
Amit Joshi Avatar answered Oct 13 '22 21:10

Amit Joshi