title: Separating the service layer from the validation layer
body: <p>I currently have a service layer based on the article <a href="https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions-1/models-data/validating-with-a-service-layer-cs" rel="noreferrer">Validating with a service layer</a> from the ASP.NET site.</p>
  
  <p>According to <a href="https://stackoverflow.com/a/4851953/577417">this</a> answer, this is a bad approach because the service logic is mixed with the validation logic which violates the single responsibility principle.</p>
  
  <p>I really like the alternative that is supplied but during re-factoring of my code I have come across a problem that I am unable to solve.</p>
  
  <p>Consider the following service interface:</p>
  
  <pre><code>interface IPurchaseOrderService
  {
      void CreatePurchaseOrder(string partNumber, string supplierName);
  }
  </code></pre>
  
  <p>with the following concrete implementation based on the linked answer:</p>
  
  <pre><code>public class PurchaseOrderService : IPurchaseOrderService
  {
      public void CreatePurchaseOrder(string partNumber, string supplierName)
      {
          var po = new PurchaseOrder
          {
              Part = PartsRepository.FirstOrDefault(p =&gt; p.Number == partNumber),
              Supplier = SupplierRepository.FirstOrDefault(p =&gt; p.Name == supplierName),
              // Other properties omitted for brevity...
          };
  
          validationProvider.Validate(po);
          purchaseOrderRepository.Add(po);
          unitOfWork.Savechanges();
      }
  }
  </code></pre>
  
  <p>The <code>PurchaseOrder</code> object that is passed to the validator also requires two other entities, <code>Part</code> and <code>Supplier</code> (let's assume for this example that a PO only has a single part).</p>
  
  <p>Both the <code>Part</code> and <code>Supplier</code> objects could be null if the details supplied by the user do not correspond to entities in the database which would require the validator to throw an exception. </p>
  
  <p>The problem I have is that at this stage the validator has lost the contextual information (the part number and the supplier name) so is unable to report an accurate error to the user. The best error I can supply is along the lines of <em>"A purchase order must have an associated part"</em> which would not make sense to the user because they did supply a part number (it just does not exist in the database).</p>
  
  <p>Using the service class from the ASP.NET article I am doing something like this:</p>
  
  <pre><code>public void CreatePurchaseOrder(string partNumber, string supplierName)
  {
      var part = PartsRepository.FirstOrDefault(p =&gt; p.Number == partNumber);
      if (part == null)
      {
          validationDictionary.AddError("", 
              string.Format("Part number {0} does not exist.", partNumber);
      }
  
      var supplier = SupplierRepository.FirstOrDefault(p =&gt; p.Name == supplierName);
      if (supplier == null)
      {
          validationDictionary.AddError("",
              string.Format("Supplier named {0} does not exist.", supplierName);
      }
  
      var po = new PurchaseOrder
      {
          Part = part,
          Supplier = supplier,
      };
  
      purchaseOrderRepository.Add(po);
      unitOfWork.Savechanges();
  }
  </code></pre>
  
  <p>This allows me to provide much better validation information to the user but means that the validation logic is contained directly in the service class, violating the single responsibility principle (code is also duplicated between service classes).</p>
  
  <p>Is there a way of getting the best of both worlds? Can I separate the service layer from the validation layer whilst still providing the same level of error information?</p>