tags:

views:

157

answers:

2

Hi

I am a bit confused about the service layer and using it validation.

So I am looking through this tutorial: http://www.asp.net/learn/mvc/tutorial-38-cs.aspx

First if you look at List 3

using System.Collections.Generic;
using System.Web.Mvc;

namespace MvcApplication1.Models
{
    public class ProductService : MvcApplication1.Models.IProductService
    {

        private ModelStateDictionary _modelState;
        private IProductRepository _repository;

        public ProductService(ModelStateDictionary modelState, IProductRepository repository)
        {
            _modelState = modelState;
            _repository = repository;
        }

        protected bool ValidateProduct(Product productToValidate)
        {
            if (productToValidate.Name.Trim().Length == 0)
                _modelState.AddModelError("Name", "Name is required.");
            if (productToValidate.Description.Trim().Length == 0)
                _modelState.AddModelError("Description", "Description is required.");
            if (productToValidate.UnitsInStock < 0)
                _modelState.AddModelError("UnitsInStock", "Units in stock cannot be less than zero.");
            return _modelState.IsValid;
        }

        public IEnumerable<Product> ListProducts()
        {
            return _repository.ListProducts();
        }

        public bool CreateProduct(Product productToCreate)
        {
            // Validation logic
            if (!ValidateProduct(productToCreate))
                return false;

            // Database logic
            try
            {
                _repository.CreateProduct(productToCreate);
            }
            catch
            {
                return false;
            }
            return true;
        }


    }

    public interface IProductService
    {
        bool CreateProduct(Product productToCreate);
        IEnumerable<Product> ListProducts();
    }
}

They same interface just with a different name basically why not just use one?

    public interface IProductRepository
    {
        bool CreateProduct(Product productToCreate);
        IEnumerable<Product> ListProducts();
    }

   public interface IProductService
    {
        bool CreateProduct(Product productToCreate);
        IEnumerable<Product> ListProducts();
    }

In my book though(the author who I think wrote this tutorial) has changed it to have IProductRepository to void. So that confuses me even more.

So can someone explain why I need 2 interfaces that seems to do the same thing?

My next questions is my repository has a delete function. Do I put this one in my Service layer too(I guess mandatory if you use one Interface but if you use 2 like about then it could be optinal).

So what would I have in my service layer? Would it just call delete function in the repository? Should it just be a void method or should it return bool? I don't think for this method any validation would need to be done?

So I am not sure if a bool would be needed.

+1  A: 

From the tutorial you are reading:

So, application flow control logic belongs in a controller and data access logic belongs in a repository. In that case, where do you put your validation logic? One option is to place your validation logic in a service layer.

A service layer is an additional layer in an ASP.NET MVC application that mediates communication between a controller and repository layer. The service layer contains business logic. In particular, it contains validation logic.

EDIT:

I'm not sure if I can explain it to you in a clear way('cause I'm not fluent in English), but I will try:

A service layer is an additional layer in an ASP.NET MVC application that mediates communication between a controller and repository layer, in that you can handle both validation and application businness. Sometimes you service will need to work with two or more methods of its correspondent repository layer so it doesnt need to have the same interface.

A basic example, let's think you have a register form.

you will have the following interfaces

public interface IUserService

{
    bool Register(User mUser);
    bool Validate(User mUser);
}

public interface IUserRepository
{
    User FindUserByEmail(string Email);
    bool Insert(User mUser);
}

so you will end up with two class that will do something like: public class UserRepository: IUserRepository{

    User FindUserByEmail(string Email)
{
    //do a ninja search and return an user or null
}
    bool Insert(User mUser);
    {
     //Insert user into db
    } 
}

public class UserService: IUserService
{
    public bool Validate(User mUser)
    {
     //validate user
    }
    IUserRepository _respository = new UserRepository();
    bool Register(User mUser)
    {
     if(Validate(mUser);
     var hasUser = _respository.FindUserByEmail(User.Email);
     if(hasUser==null)
      return _respository.Insert(mUser);
     return false;
    } 
}
Cleiton
Sorry I am not following. I don't still see why you can't use the same interface and instead make 2 different interfaces that have the exact same methods. Still not sure about the delete one either should it be return something or not?
chobo2
chobo2, i edited my answer to explain what it means to you(it tooks so long time from me to write down LOL)
Cleiton
That helps alot. How about if you have to call another repository? Would you call it in the service layer or would you call it in your controller?
chobo2
@chobo2, I would recommend rolling similar repositories into one service. I think this question will help you http://stackoverflow.com/questions/325984/service-layers-and-repositories
Cleiton
A: 

I think you've made an argument for a single interface in this limited case, but the service and repositories perform two very different functions and you may run into issues down the road if they shared a single interface.

What if the CreateProduct() or ListProducts() needed to have different method signatures in either the service or repository?

What if ValidateProduct() should be defined in the interface? The repository certainly shouldn't have to implement that.

As you've pointed out, there's no need for two interfaces that define the same thing in this particular example, but I assume the author's assumption is that down the road they would be different and therefore necessary.

Kurt Schindler
Hmm I sort of see your point but I think I would need more of an example. I am trying to think why CreateProduct would have a different method signature. Like the service layer hooks up to the repository either way and if your going to create a product it has to have those fields that correspond to the database. So I don't see what CreateProduct would ever send in differently in then a Product that needs to be created with those fields.
chobo2
On a side not the example he gives in his book(I think that tutorial was written by the guy who wrote asp.net mvc unleashed). He does not even have a ValidateProduct(). He did the validation directly in the Create method.
chobo2
I misread the code at first (Validate... is a protected method only called in the Create method) so that is why it wouldn't be in the interface in this case. The difference between his book and this is just a little refactoring.
Kurt Schindler
So what would be better then? Having it ValidateProduct() in the interface? Or to have it protected? Well I would think splitting it up to its own method would be better and I would consider it to be re factoring. I am still not 100% clear why the to interfaces and would love to see an actual example when having 2 would be better than one.
chobo2