ASP.NET MVC Patterns

后端 未结 4 1158
一向
一向 2021-01-15 09:07

I am fairly new to MVC, but after playing with it (MVC 3/Razor), I am hooked.

I have a few questions:

1) What is the best, or most widely used pattern to dev

相关标签:
4条回答
  • 2021-01-15 09:32

    I use generic repositories that get instantiated in a service class (using Dependency Injection with Ninject).

    The service class essentially performs two functions:

    1. It provides all the methods that the controller will consume.

    2. It has a property called ViewModel, that essentially maps the data that the views need into a MyViewModel class.

    The Controller consumes the service class. With this "pattern", your controllers look like:

    namespace ES.eLearningFE.Areas.Courses.Controllers
    {
        public partial class CourseController : Controller
        {
            ICourseDisplayService service;
            public CourseController(ICourseDisplayService service)
            {
                this.service = service;
            }
    
            public virtual ActionResult Display(int CourseId, int StepOrder, string PupilName, string TutorName)
            {
                service.CourseId = CourseId;
                service.StepOrder = StepOrder;
                service.PupilName = PupilName;
                service.TutorName = TutorName;
                if (Request.IsAjaxRequest())
                {
                    return PartialView(service.ViewModel);
                }
                else
                {
                    return View(service.ViewModel);
                }
            }
    
        }
    }
    

    The ViewModel class only hold display data and no methods (except the odd really simple method to retrieve data from another property that is, for example a List<> object).

    Works really well. An example of a service class:

    namespace ES.eLearning.Domain.Services.Courses
    {
        public class SqlCourseDisplayService : ICourseDisplayService
        {
            DataContext db;
    
            public SqlCourseDisplayService(DbDataContextFactory contextFactory)
            {
                db = contextFactory.Make();
                CoursesRepository      = new SqlRepository<Course>(db);
                StepsRepository        = new SqlRepository<CourseStep>(db);
                StepLinksRepository    = new SqlRepository<StepLink>(db);
                UserCoursesRepository  = new SqlRepository<UserCourse>(db);
                CourseTutorsRepository = new SqlRepository<CourseTutor>(db);
                UsersRepository        = new SqlRepository<User>(db);
            }
            #region ICourseDisplayService Members
    
            public ViewModels.CourseDisplayVM ViewModel
            {
                get
                {
                    return new ViewModels.CourseDisplayVM
                    {
                        CourseId = this.CourseId,
                        CourseName = this.Course.Name,
                        Steps = this.Steps,
                        ActiveStepIndex = this.ActiveStepIndex,
                        CurrentStepIndex = this.CurrentStepIndex,
                        Pupil = new UserDto { UserId = this.PupilId, UserName = this.PupilName },
                        Tutors = this.GetTutors(this.CourseId),
                        Tutor = tutorName == null ? null : new UserDto { UserName = this.TutorName, UserId = this.TutorId}
                    };
                }
            }
    
            #region Entities
    
            int courseId;
            public int CourseId
            {
                get
                {
                    if (courseId == 0) throw new ApplicationException("Invalid Course Id!");
                    return courseId;
                }
                set
                {
                    if (value == 0) throw new ApplicationException("Invalid Course Id!");
                    try
                    {
                        Course   = (from c in CoursesRepository.Query where c.CourseId == value select c).First();
                        Steps    = Course.CourseSteps.ToList();
                        courseId = value;
                    }
                    catch {throw new ApplicationException("No Course found for Course Id: " + value);}
                }
            }
    
            public Data.Course Course { get; private set; }
    
            public int StepOrder { get; set; }
    
            public List<Data.CourseStep> Steps { get; private set; }
    
            public int ActiveStepIndex
            {
                get
                {
                    if (PupilName == null)
                    {
                        throw new ApplicationException("Pupil not set!");
                    }
                    if (CourseId == 0)
                    {
                        throw new ApplicationException("Course not set!");
                    }
                    try
                    {
                        var x = (from uc in UserCoursesRepository.Query where (uc.IdCourse == CourseId) && (uc.UserName == PupilName) select uc).First();
                        return x.ActiveStepIndex;
                    }
                    catch { throw new ApplicationException("Could not get Active Step!"); }
                }
            }
    
            #endregion
    
            #region Users
    
            string tutorName;
            public string TutorName
            {
                get 
                {
                    if (tutorName == null) throw new ApplicationException("Invalid call to get Tutor Name [Null Tutor Name]!");
                    return tutorName; 
                }
                set
                {
                    tutorName = value;
                    TutorId = (Guid)Membership.GetUser(tutorName).ProviderUserKey;
                }
            }
    
            public Guid TutorId { get; set; }
    
            string pupilName;
            public string PupilName
            {
                get { return pupilName; }
                set
                {
                    pupilName = value;
                    PupilId = (Guid)Membership.GetUser(pupilName).ProviderUserKey;
                }
            }
    
            public Guid PupilId { get; set; }
    
            #endregion
    
            #region Utility Properties
    
            public int CurrentStepIndex { get; set; }
            public int StepCount
            {
                get
                {
                    return Steps == null ? 0 : Steps.Count();
                }
            }
    
            #endregion
    
            #region Private Utilities
    
            private List<UserDto> GetTutors(int CourseId)
            {
                return (from ct in CourseTutorsRepository.Query join u in UsersRepository.Query
                        on ct.TutorName equals u.UserName
                        where (ct.CourseId == courseId) 
                        select new UserDto { UserName = ct.TutorName, UserId = u.UserId }).ToList();
            }
    
            #endregion
    
            #region Repositories
    
            private IRepository<Course> CoursesRepository
            {
                get;
                set;
            }
    
            private IRepository<CourseStep> StepsRepository
            {
                get;
                set;
            }
    
            private IRepository<StepLink> StepLinksRepository
            {
                get;
                set;
            }
    
            private IRepository<UserCourse> UserCoursesRepository
            {
                get;
                set;
            }
    
            private IRepository<CourseTutor> CourseTutorsRepository
            {
                get;
                set;
            }
    
            private IRepository<User> UsersRepository
            {
                get;
                set;
            }
    
            #endregion
    
            #endregion
        }
    }
    

    May not be everyone's choice, but hey, it works for me... AND (more importantly) my clients and their users.

    Edit

    As requested in the comment below, the Repository that I use:

    namespace ES.eLearning.Domain
    {
        public class SqlRepository<T> : IRepository<T> where T : class
        {
            DataContext db;
            public SqlRepository(DataContext db)
            {
                this.db = db;
            }
    
            #region IRepository<T> Members
    
            public IQueryable<T> Query
            {
                get { return db.GetTable<T>(); }
            }
    
            public List<T> FetchAll()
            {
                return Query.ToList();
            }
    
            public void Add(T entity)
            {
                db.GetTable<T>().InsertOnSubmit(entity);
            }
    
            public void Delete(T entity)
            {
                db.GetTable<T>().DeleteOnSubmit(entity);
            }
    
            public void Attach(T entity)
            {
                db.GetTable<T>().Attach(entity);
            }
    
            public void Save()
            {
                db.SubmitChanges();
            }
    
            #endregion
        }
    }
    

    And the IRepository Interface:

    namespace Wingspan.Web.Mvc
    {
        public interface IRepository<TEntity> where TEntity : class
        {
            List<TEntity> FetchAll();
            IQueryable<TEntity> Query {get;}
            void Add(TEntity entity);
            void Delete(TEntity entity);
            void Attach(TEntity entity);
            void Save();
        }
    }
    
    0 讨论(0)
  • 2021-01-15 09:34

    1) I would say that the repository pattern is the most widely used, then there is inversion of controll too.

    2) I can't really point out the benefits with using a repository for entity framework other than that the controller should not know about how to acces data other then asking a repository. This makes it easy to switch it out sometime. You can also eager load the data to make sure that the view don't call the database in every iteration of a foreach, for example a collection of users to display data from a child entity. You can probly do this anyway, but I feel that the repository is the right place to do it.

    3) I can't tell you about the concept in a more in depth way, but I can tell some about viewmodels. In my opinion you should only use viewmodels if there is anything more then one entity you want to send to the view, for example a list of countries. You can alo use a viewmodel to "flatten" out very complex objects.

    0 讨论(0)
  • 2021-01-15 09:43

    This should help you getting started. There are a lot of tutorials and videos available; for example:

    • Understanding Models, Views and Controllers
    • The ASP.NET MVC 2.0 basics and excellent introduction by Scott Hanselman. Personally one of my favorite speakers.

    And also at www.asp.net; there are a few tutorials/examples to help you getting started. For example the Music Store sample

    Unfortunately, I'm not so familiar with EF4/Repository pattern. But here's a blogpost about this pattern.

    0 讨论(0)
  • 2021-01-15 09:44

    I would defiantly say the repository pattern is used a lot. This pattern can be used with Dependency Injection. Using Dependency Injection makes Unit Testing a breeze because you can snap different repositories to an abstract repoistory. Check out http://ninject.org/ for a simple to use Dependecy injector for .NET.

    View Models should hold display data and transfer that data from the controller to the view. If you want to edit and display customer info, take a look at this

    0 讨论(0)
提交回复
热议问题