3 Replies - 9735 Views - Last Post: 20 February 2013 - 08:00 PM

#1 regex  Icon User is offline

  • New D.I.C Head

Reputation: -4
  • View blog
  • Posts: 33
  • Joined: 25-September 12

MVC 4 Pattern: Controller, Service, Repository

Posted 19 February 2013 - 10:24 PM

I have a template controller, service, and repository. I am trying to coordinate the activities here to generate a list of templates, ability to edit, and create. Typical CRUD methods.

(1) Am I doing this right?
- Should I store my domain in the TemplateRepository and pass it to the service and controller like I'm doing?

(2) How do I reference ViewModels in the service? Just wrap them in methods in the service class?

(3) My biggest challenge is plumbing this to the views. I want to display a list of all templates with an Edit link, Create New Link, and a delete link. Can anyone provide some tips on that side? Thank you!

(4) I've been refactoring my code all night. I originally had the "public IList<TemplateListViewModel> GetAllTemplates()" method encapsulating "TemplateListViewModel". Would that method be better served by referencing the ViewModel instead of my current dev?

I have a model/service:

using HtmlAgilityPack;
using IDM.CMS3.Service.Models;
using Raven.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using IDM.CMS3.Service.ViewModels.Templates;

namespace IDM.CMS3.Service.Services
{
    public interface ITemplateService
    {
        void Save(string content);
        void AddTemplate(TemplateListViewModel template);
        void DeleteTemplate(Guid id);
    }

    public class TemplateService : ITemplateService
    {
        IDocumentSession _documentSession;
        TemplateRepository _repository;
 
        public TemplateService(TemplateRepository repository)
        {
            //_documentSession = documentSession;
            _repository = repository; 
        }
        
        public IList<Template> GetAllTemplates()
        {
            return _repository.GetAllTemplates();
        }

        public void AddTemplate(Template newTemplate)
        {
            _repository.AddTemplate(newTemplate); 
        }

        public Template GetTemplate(int TemplateAdminId)
        {
            return _repository.GetTemplate(TemplateAdminId);
        }

        public void DeleteTemplate(int TemplateAdminId)
        {
            _repository.DeleteTemplate(TemplateAdminId);
        }
    }

        public void Save(string content)
        {
            //parse(content);

            PageTemplate tm = new PageTemplate
            {
                Id = "site/1",
                Text = content
            };

            _documentSession.Store(tm);
            _documentSession.SaveChanges();

        }

        void parse(string content)
        {
            HtmlDocument document = new HtmlDocument();
            string htmlString = "<a href>test.com</a>";
            string target;
            document.LoadHtml(htmlString);
            HtmlNodeCollection collection = document.DocumentNode.SelectNodes("//a");
            //var session = store.OpenSession(); 

            foreach (HtmlNode link in collection)
            {
                target = link.Attributes["href"].Value;
            }
        }
    }
}




I have a controller which calls the service and another model:


using System.Web.Mvc;
using IDM.CMS3.Web.Admin.Models;
using Raven.Abstractions.Data;
using Raven.Client;
using Raven.Client.Document;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using IDM.CMS3.Service.Models;
using Raven.Client.Indexes;
using IDM.CMS3.Service.App_Start;
using Raven.Abstractions.Indexing;
using IDM.CMS3.Service.Models.PageWidgets;
using System.IO;
using System.Reflection;
using IDM.CMS3.Service.Services;
using IDM.CMS3.Service.Models; 


//using IDM.CMS3.Data.DTO;

namespace IDM.CMS3.Web.Admin.Controllers
{
    public class TemplateController : Controller
    {
        readonly TemplateRepository _templateRepository;
        readonly TemplateService _templateService; 

        public TemplateController(TemplateService templateService, TemplateRepository templateRepository)
        {
            _templateService = templateService;
            _templateRepository = templateRepository;
        }

        public ActionResult Index()
        {
            TemplateService service = new TemplateService(_templateRepository);
            return View(service.GetAllTemplates());
        }
        [HttpPost]
        public ActionResult Details(int templateAdminId = 0)
        {
            TemplateService service = new TemplateService(_templateRepository);
            Template template = service.GetTemplate(templateAdminId);
            if (template == null)
            {
                return HttpNotFound(); 
            }
            return View(template); 
        }
        
        [HttpPost]
        public ActionResult Create(Template template)
        {
            if (ModelState.IsValid)
            {
                TemplateService service = new TemplateService(_templateRepository);
                service.AddTemplate(template); 
                return RedirectToAction("Index", "TemplateController"); 
            }
            return View(template); 
        }
        public ActionResult Delete(int templateAdminId = 0)
        {
            TemplateService service = new TemplateService(_templateRepository);
            Template template = service.GetTemplate(templateAdminId);
            if (template == null)
            {
                return HttpNotFound(); 
            }
            return View(template); 
        }

        [HttpPost]
        public ActionResult Save(TemplateViewModel content)
        {
            _templateService.Save(content.Content);
            return View();
        }


        
        //public void Save()
        //{
        //    HtmlDocument document = new HtmlDocument();
        //    string htmlString = "<a href>test.com</a>";
        //    string target;
        //    document.LoadHtml(htmlString);
        //    HtmlNodeCollection collection = document.DocumentNode.SelectNodes("//a");
        //    var session = store.OpenSession();  

        //    store = new DocumentStore
        //    {
        //        Url = RavenUrl,
        //        DefaultDatabase = "WebCMS",
        //    };
 
        //    foreach (HtmlNode link in collection)
        //    {
        //        target = link.Attributes["href"].Value;

        //    }

        //    TemplateModel t0 = new TemplateModel()
        //    {
        //        Content = "test", 
               
        //    };
            
        //    session.Store(t0);

        //    session.SaveChanges();
        //}

    }
}


Finally, I have a TemplateRepository:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using IDM.CMS3.Service.ViewModels.Templates;
using IDM.CMS3.Service.Models;


namespace IDM.CMS3.Service.Models
{
    public class TemplateRepository : ModelBase
    {
        public IList<Template> GetAllTemplates();
        IList<Template> GetTemplates(int userId);
        public void AddTemplate(Template template);
        public Template GetTemplate(int TemplateAdminId);
        public void DeleteTemplate(int TemplateAdminId);
    }
}




I also have a model for the singular Template:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IDM.CMS3.Service.Models
{
    public class Template
    {
        public string Name { get; set; }
        public string Category { get; set; }
        public int TemplateAdminId { get; set; }
    }
}


This post has been edited by regex: 19 February 2013 - 10:26 PM


Is This A Good Question/Topic? 0
  • +

Replies To: MVC 4 Pattern: Controller, Service, Repository

#2 Nakor  Icon User is offline

  • Professional Lurker
  • member icon

Reputation: 444
  • View blog
  • Posts: 1,492
  • Joined: 28-April 09

Re: MVC 4 Pattern: Controller, Service, Repository

Posted 20 February 2013 - 07:09 AM

One question I have: You are passing a TemplateService object into your constructor and setting the local service equal to the passed in value. That sets the value for your service. Is there a reason you then need to create a new TemplateService object in every action method?

The reason I ask this is because when the instance of TemplateService that is injected into your controller is being created it should be getting created with an instance of the repository.

Your controller really shouldn't know, or care, about your repository or your data classes. It should work directly with the viewmodel(s) and the service object. Pass the ViewModel to the service object and let it take care of converting between the viewmodel and the data model.

I don't see any code for anything called TemplateViewModel. It looks like you're just working directly with the Template model everywhere. Which I'm assuming is the data model since it is what is being used by the repository.

The MVC-Music-Store is a pretty decent tutorial for learning MVC.

This post has been edited by Nakor: 20 February 2013 - 07:17 AM

Was This Post Helpful? 0
  • +
  • -

#3 regex  Icon User is offline

  • New D.I.C Head

Reputation: -4
  • View blog
  • Posts: 33
  • Joined: 25-September 12

Re: MVC 4 Pattern: Controller, Service, Repository

Posted 20 February 2013 - 08:19 AM

Thank you for the recommendations Nakor. I did refactor according to your input. I turned each new instance of this:
TemplateService service = new TemplateService(_templateRepository);
into this:
return View(_templateService.GetAllTemplates());


Two main questions remain. How do I wrap a ViewModel in my service object and furthermore how do I ultimately retrofit this to the View?

By the way, here is the TemplateEditViewModel:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IDM.CMS3.Service.ViewModels.Templates
{
    class TemplateEditViewModel
    {
        public Guid Id { get; set; }
        public string Name { get; set; }

        public TemplarEditModel[] Templars { get; set; }

        public class TemplarEditModel
        {
            public Guid Id { get; set; }
            public string Content { get; set; }
        }
    }
}


The TemplateListViewModel:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading.Tasks;
using System.Web.Mvc;

namespace IDM.CMS3.Service.ViewModels.Templates
{
    public class TemplateListViewModel
    {
        public Guid Id { get; set; }
        [HiddenInput(DisplayValue = false)]
        public string Name { get; set; }
        public string Category { get; set; }
    }
}



Was This Post Helpful? 0
  • +
  • -

#4 Nakor  Icon User is offline

  • Professional Lurker
  • member icon

Reputation: 444
  • View blog
  • Posts: 1,492
  • Joined: 28-April 09

Re: MVC 4 Pattern: Controller, Service, Repository

Posted 20 February 2013 - 08:00 PM

You have two options for your view, one is to pass the ViewModel to the view directly from the controller. The second option is to load the page and use an ajax call to retrieve the ViewModel as the page loads.

The first option is easiest if you're not that comfortable with javascript. You should be able to specify the ViewModel when you create the view. If you are using razer syntax the top of the view should start with something like

@model TemplateListViewModel



or for a list of ViewModels

@model List<TemplateListViewModel>



In your service class, you should take a ViewModel object as a parameter in your CRUD methods. In the Create method you would create a new Template object with the values of the ViewModel object and pass the new Template object to the repository. For Delete you would just need to pass the id from the ViewModel object into your Delete method. When selecting data in your service you will need to convert the Template object(s) into ViewModel object(s) and return the ViewModel object(s) to the controller which will then pass them to the View.

Your controller actions should, in general, be very clean. An example might be similar to this:

public ActionResult Create(MyViewModel model)
{
    if (ModelState.IsValid)
    {
        service.Add(model);
        return View("SomeView");
    }

    return View(model);
}

public ActionResult TemplateList()
{
    return View(service.GetAll());
}


This post has been edited by Nakor: 20 February 2013 - 08:05 PM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1