Apply to request response pattern in your service layer

Messaging pattern is one of my favorite patterns to use in service layer! since I've read Pro Asp.net Design pattern by ScottMillett I've been a big fan of patterns and how to apply them, in this article I'm going to talk about request response pattern.

"Design patterns that are associated in the realm of large-scale distributed applications like SOA systems are often referred to as Messaging patterns. Messaging patterns, like Design patterns, provide standard solutions to complex problems. Messaging patterns tackle the sharing of data in a uniform manner among many disconnected systems." ~@ScottMillett

So let's implement it , I'm going to define the News part of a project that I'm tackling with at the moment , I will just implement two operation, I have defined these methods in INewsService :

CreateNews , GetNews , GetAllNews , UpdateNews , RemoveNews , GetNewsByDate , GetAllArchivedNewsByDate

And I'm discussing about CreateNews and GetAllArchivedNewsByDate .So For each of them I should create a response and a request class . let's begin by creating the messaging classes

  1.     public class CreateNewsResponse
  2.     {
  3.        public NewsViewModel PostViewModel { get; set; }
  4.     }

This response class that returns a property of NewsViewModel type lets me to access the NewsViewModel properties.  and about CreateNewsRequest I usually create a constructor contained newsViewModel as parameter to make it using the method in service implementation and also Presentation simple

  1.     public class CreateNewsRequest
  2.     {
  3.         internal NewsViewModel NewsViewModel { get; private set; }
  4.         public CreateNewsRequest(NewsViewModel newsViewModel)
  5.         {
  6.             NewsViewModel = newsViewModel;
  7.         }
  8.     }

Now in INewsService interface , define the CreateNews like this

  1.     public interface INewsService
  2.     {
  3.              CreateNewsResponse CreateNews(CreateNewsRequest request);
  4.     }

As you can see CreateNews contains a response as an output and a request as a parameter. And as I promised , I Create messaging classes of GetAllArchivedNewsByDate :

  1.     public class GetAllNewsRequest
  2.     {
  3.         internal NewsViewModel NewsViewModel { get; private set; }
  4.         internal int Year { get; private set; }
  5.         internal int Month { get; private set; }
  6.        
  7.         public GetAllNewsRequest(NewsViewModel newsViewModel)
  8.         {
  9.             NewsViewModel = newsViewModel;
  10.         }
  11.         public GetAllNewsRequest(int year, int month)
  12.         {
  13.             Year = year;
  14.             Month = month;
  15.         }
  16.     }

As you see in the request class I've defined two constructor , first one is the same you saw in CreateNewsRequest and the second one take two parameter (year and month) because I need this constructor in presentation layer that you will see later!

And about response class

  1.     public class GetAllNewsResponse
  2.     {
  3.         public IEnumerable<NewsViewModel> PostViewModels { get; set; }
  4.     }

It returns an Ienumerable of NewsViewModel cause it maybe have more than one news in a date.

And then in INewsService I have to define the GetAllArchivedNewsByDate like this :

  1.     public interface INewsService
  2.     {
  3.              CreateNewsResponse CreateNews(CreateNewsRequest request);
  4.              GetAllNewsResponse GetAllArchivedNewsByDate(GetAllNewsRequest request);
  5.     }

Well , about implementing this methods in NewsService take a closer look at NewsService :

  1.     public class NewsService : INewsService
  2.     {
  3.         private readonly INewsRepository _newsPostRepository;
  4.         private readonly IUnitOfWork _unitOfWork;
  5.         public NewsService(INewsRepository newsPostRepository , IUnitOfWork unitOfWork)
  6.         {
  7.             _newsPostRepository = newsPostRepository;
  8.             _unitOfWork = unitOfWork;
  9.         }
  10.         public CreateNewsResponse CreateNews(CreateNewsRequest request)
  11.         {
  12.             var response = new CreateNewsResponse();
  13.             var newsPost = request.NewsViewModel.ConvertToNewsPostModel();
  14.             newsPost.CreationTime = DateTime.Now;
  15.             newsPost.NewsSlug = request.NewsViewModel.Title.GenerateSlug();
  16.             _newsPostRepository.Add(newsPost);
  17.              _unitOfWork.SaveChanges();
  18.             return response;
  19.         } 
  20.         public GetAllNewsResponse GetAllArchivedNewsByDate(GetAllNewsRequest request)
  21.         {
  22.             var response = new GetAllNewsResponse();
  23.             var newses = _newsPostRepository.GetAllArchivedNewsByDateQuery(request.Year, request.Month);
  24.             response.PostViewModels = newses.ConvertToNewsViewModelList();
  25.             return response;
  26.         }

Notice about GetAllArchivedNewsByDateQuery method , it's defined in Repository layer and it returns a value by Query Object pattern from database.

And about ConvertToNewsViewModelList and ConvertToNewsPostModel I've talked about before in automapper article ,I use extension method to convert objects to each other.

So if you are solicitous about how to use these service in presentation layer , take a look again! I'm using MVC4 in UI , here is what I've done in controller :

  1.     public class NewsController : BaseController
  2.     {
  3.         private readonly INewsService _newsService;
  4.         public NewsController(ICookieStorageService cookieStorageService, INewsService newsService)
  5.             : base(cookieStorageService)
  6.         {
  7.             _newsService = newsService;
  8.         }
  9.        public ActionResult Create()
  10.         {
  11.             return View("Create");
  12.         }
  13.         [HttpPost]
  14.         public ActionResult Create(NewsViewModel newsViewModel)
  15.         {
  16.             var createNewsRequest = new CreateNewsRequest(newsViewModel);
  17.             if (ModelState.IsValid)
  18.             {
  19.                 _newsService.CreateNews(createNewsRequest);
  20.                  return View("Create");
  21.             }
  22.             return View("Create");
  23.         }
  24.         public ActionResult Archive(int year, int month)
  25.         {
  26.             var request = new GetAllNewsRequest(year, month);
  27.             var newses = _newsService.GetAllArchivedNewsByDate(request);
  28.             return View("Archive", newses.PostViewModels);
  29.         }
  30.    }

As you can see in Archive ActionResult  I just used second constructor of GetAllNewsRequest and also can use any constructor if I need! Thanks for reading this and have a good time...


Tags: Design Pattern C#


comments powered by Disqus