Saturday, 13 September 2014

Repository Pattern and Unit of Work with Entity Framework in ASP.NET MVC

In previous tutorial you used basic CRUD (Create, Read, Update and Delete) functionality with entity framework and by using jquery dialog(s) in asp.net mvc. In this you’ll see some ways to use the repository and unit of work patterns for CRUD operations.

The repository and unit of work patterns are intended to create an abstraction layer between the data access layer and the business logic layer of an application. Implementing these patterns can help insulate your application from changes in the data store and facilitate automated unit testing or test-driven development (TDD).

Let’s start with the implementation of Repository and Unit of Work patterns in a tutorial. If you have gone through my previous tutorial then start with where it ends and if you do not have experience about previous tutorial please download the sample of previous tutorial and start with that.

1)      In the current solution, add three new class library project:

a)      Sample.Model

b)      Sample.Data.Contracts

c)       Sample.Data

Our solution explorer will something look like this:

                                ManagingMultijQueryForm

                                Sample.Data

                                Sample.Data.Contracts

                                Sample.Model

 

2)      Delete Category, SubCategory and Product class from the web project i.e. ManagingMultijQueryForm and add these classes in Sample.Model project. Also add reference of System.ComponentModel.DataAnnotations in order to use the (Required and Display) attribute.

 

a)      Category class (Category.cs):

public class Category

       {

           public int CategoryID { get; set; }

 

           [Required]

           public string Name { get; set; }

       }

b)      SubCategory class (SubCategory.cs):

    public class SubCategory

    {

        public int SubCategoryID { get; set; }

 

        public virtual Category Category { get; set; }

 

        [Display(Name = "Category")]

        public int CategoryID { get; set; }

 

        [Required]

        public string Name { get; set; }

    }

c)       Product class (Product.cs):

    public class Product

    {

        public int ProductID { get; set; }

 

        [Required]

        public string Name { get; set; }

 

        [Required]

        public string Description { get; set; }

 

        public virtual SubCategory SubCategory { get; set; }

 

        [Display(Name = "Sub Category")]

        public int SubCategoryID { get; set; }

    }

 

3)      In Sample.Data.Contracts add two interface IRepository (for repositories) and IProductUow ( for unit of work). Before creating the interfaces add the reference of Sample.Model in Sample.Data.Contracts

 

a)      IRepository.cs, it is generic interface:

    public interface IRepository<T> where T: class

    {

        IQueryable<T> GetAll();

        T GetById(int id);

        void Add(T entity);

        void Update(T entity);

        void Delete(T entity);

        void Delete(int id);

    }

b)      IProductUow.cs :

    public interface IProductUow

    {

        // Save pending changes to the data store.

        void Commit();

 

        // Repositories

        IRepository<Product> Products { get; }

        IRepository<Category> Categories { get; }

        IRepository<SubCategory> SubCategories { get; }

    }

4)      In Sample.Data project, add the reference of Sample.Model and Sample.Data.Contracts and install entity framework via package manager console  (Tools à Library Package Manager à Package Manager Console) by using following command:

Install-package entityframework

5)      Delete ProductDbContext, ProductDbContextInitializer from the web project and add these classes in Sample.Data project:

 

a)      ProductDbContext class (ProductDbContext.cs):

    public class ProductDbContext : DbContext

    {

        public ProductDbContext()

            : base(nameOrConnectionString: "Data Source=SONY-VAIO\\SQLEXPRESS;Initial Catalog=ProductDbContext;Integrated Security=true;")

        {

            Database.SetInitializer(new ProductDbContextInitializer());

        }

 

        protected override void OnModelCreating(DbModelBuilder modelBuilder)

        {

            // Use singular table names

            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

            base.OnModelCreating(modelBuilder);

        }

 

        public DbSet<Product> Product { get; set; }

        public DbSet<Category> Category { get; set; }

        public DbSet<SubCategory> SubCategory { get; set; }

    }

b)      ProductDbContextInitializer class (ProductDbContextInitializer.cs)

public class ProductDbContextInitializer : DropCreateDatabaseIfModelChanges<ProductDbContext>

    {

        protected override void Seed(ProductDbContext context)

        {

            List<Category> categories = new List<Category>

            {

                new Category { Name = "Food" },

                new Category { Name = "Electronics" },

                new Category { Name = "Beverages" }

            };

 

            List<SubCategory> subcategories = new List<SubCategory>

            {

                new SubCategory { Name = "Vegetables", Category = categories.Find(m => m.Name.Equals("Food")) },

                new SubCategory { Name = "Fruits", Category = categories.Find(m => m.Name.Equals("Food")) },

                new SubCategory { Name = "Computer", Category = categories.Find(m => m.Name.Equals("Electronics")) },

                new SubCategory { Name = "Television", Category = categories.Find(m => m.Name.Equals("Electronics")) },

                new SubCategory { Name = "Cold Drinks", Category = categories.Find(m => m.Name.Equals("Beverages")) },

                new SubCategory { Name = "Beer", Category = categories.Find(m => m.Name.Equals("Beverages")) },

            };

 

            List<Product> products = new List<Product>

            {

                new Product { Name = "Wheat", Description = "Wheat", SubCategory = subcategories.Find(m => m.Name.Equals("Vegetables")) },

                new Product { Name = "Apple", Description = "Apple", SubCategory = subcategories.Find(m => m.Name.Equals("Fruits")) },

                new Product { Name = "Desktop", Description = "Desktop", SubCategory = subcategories.Find(m => m.Name.Equals("Computer")) },

                new Product { Name = "LG", Description = "LG", SubCategory = subcategories.Find(m => m.Name.Equals("Television")) },

                new Product { Name = "Sprite", Description = "Sprite", SubCategory = subcategories.Find(m => m.Name.Equals("Cold Drinks")) },

                new Product { Name = "Kingfisher", Description = "Kingfisher", SubCategory = subcategories.Find(m => m.Name.Equals("Beer")) },

            };

 

            categories.ForEach(m => context.Category.Add(m));

            subcategories.ForEach(m => context.SubCategory.Add(m));

            products.ForEach(m => context.Product.Add(m));

 

            context.SaveChanges();

 

            base.Seed(context);

        }

    }

c)       Create new EFRepository class which implements IRepository interface for doing CRUD by using entity framework:

    /// <summary>

    /// The EF-dependent, generic repository for data access

    /// </summary>

    /// <typeparam name="T">Type of entity for this Repository.</typeparam>

    public class EFRepository<T> : IRepository<T> where T : class

    {

        public EFRepository(DbContext dbContext)

        {

            if (dbContext == null)

                throw new ArgumentNullException("dbContext");

            DbContext = dbContext;

            DbSet = DbContext.Set<T>();

        }

 

        protected DbContext DbContext { get; set; }

 

        protected DbSet<T> DbSet { get; set; }

 

        public virtual IQueryable<T> GetAll()

        {

            return DbSet;

        }

 

        public virtual T GetById(int id)

        {

            return DbSet.Find(id);

        }

 

        public virtual void Add(T entity)

        {

            DbEntityEntry dbEntityEntry = DbContext.Entry(entity);

            if (dbEntityEntry.State != EntityState.Detached)

            {

                dbEntityEntry.State = EntityState.Added;

            }

            else

            {

                DbSet.Add(entity);

            }

        }

 

        public virtual void Update(T entity)

        {

            DbEntityEntry dbEntityEntry = DbContext.Entry(entity);

            if (dbEntityEntry.State == EntityState.Detached)

            {

                DbSet.Attach(entity);

            }

            dbEntityEntry.State = EntityState.Modified;

        }

 

        public virtual void Delete(T entity)

        {

            DbEntityEntry dbEntityEntry = DbContext.Entry(entity);

            if (dbEntityEntry.State != EntityState.Deleted)

            {

                dbEntityEntry.State = EntityState.Deleted;

            }

            else

            {

                DbSet.Attach(entity);

                DbSet.Remove(entity);

            }

        }

 

        public virtual void Delete(int id)

        {

            var entity = GetById(id);

            if (entity == null) return; // not found; assume already deleted.

            Delete(entity);

        }

    }

6)      Add Helpers folder in Sample.Data project and in that folder create a interface IRepositoryProvider and two classes (RepositoryProvider and RepositoryFactories) in order to create and find repository by using factory pattern:

 

a)      IRepositoryProvider.cs

 

    /// <summary>

    /// Interface for a class that can provide repositories by type.

    /// The class may create the repositories dynamically if it is unable

    /// to find one in its cache of repositories.

    /// </summary>

    /// <remarks>

    /// Repositories created by this provider tend to require a <see cref="DbContext"/>

    /// to retrieve data.

    /// </remarks>

    public interface IRepositoryProvider

    {

        /// <summary>

        /// Get and set the <see cref="DbContext"/> with which to initialize a repository

        /// if one must be created.

        /// </summary>

        DbContext DbContext { get; set; }

 

        /// <summary>

        /// Get an <see cref="IRepository{T}"/> for entity type, T.

        /// </summary>

        /// <typeparam name="T">

        /// Root entity type of the <see cref="IRepository{T}"/>.

        /// </typeparam>

        IRepository<T> GetRepositoryForEntityType<T>() where T : class;

 

        /// <summary>

        /// Get a repository of type T.

        /// </summary>

        /// <typeparam name="T">

        /// Type of the repository, typically a custom repository interface.

        /// </typeparam>

        /// <param name="factory">

        /// An optional repository creation function that takes a <see cref="DbContext"/>

        /// and returns a repository of T. Used if the repository must be created.

        /// </param>

        /// <remarks>

        /// Looks for the requested repository in its cache, returning if found.

        /// If not found, tries to make one with the factory, fallingback to

        /// a default factory if the factory parameter is null.

        /// </remarks>

        T GetRepository<T>(Func<DbContext, object> factory = null) where T : class;

 

 

        /// <summary>

        /// Set the repository to return from this provider.

        /// </summary>

        /// <remarks>

        /// Set a repository if you don't want this provider to create one.

        /// Useful in testing and when developing without a backend

        /// implementation of the object returned by a repository of type T.

        /// </remarks>

        void SetRepository<T>(T repository);

    }

 

b)      RepositoryProvider.cs

 

    /// <summary>

    /// Provides an <see cref="IRepository{T}"/> for a client request.

    /// </summary>

    /// <remarks>

    /// Caches repositories of a given type so that repositories are only created once per provider.

    /// Product application creates a new provider per client request.

    /// </remarks>

    public class RepositoryProvider : IRepositoryProvider

    {

        public RepositoryProvider(RepositoryFactories repositoryFactories)

        {

            _repositoryFactories = repositoryFactories;

            Repositories = new Dictionary<Type, object>();

        }

 

        /// <summary>

        /// Get and set the <see cref="DbContext"/> with which to initialize a repository

        /// if one must be created.

        /// </summary>

        public DbContext DbContext { get; set; }

 

        /// <summary>

        /// Get or create-and-cache the default <see cref="IRepository{T}"/> for an entity of type T.

        /// </summary>

        /// <typeparam name="T">

        /// Root entity type of the <see cref="IRepository{T}"/>.

        /// </typeparam>

        /// <remarks>

        /// If can't find repository in cache, use a factory to create one.

        /// </remarks>

        public IRepository<T> GetRepositoryForEntityType<T>() where T : class

        {

            return GetRepository<IRepository<T>>(

                _repositoryFactories.GetRepositoryFactoryForEntityType<T>());

        }

 

        /// <summary>

        /// Get or create-and-cache a repository of type T.

        /// </summary>

        /// <typeparam name="T">

        /// Type of the repository, typically a custom repository interface.

        /// </typeparam>

        /// <param name="factory">

        /// An optional repository creation function that takes a DbContext argument

        /// and returns a repository of T. Used if the repository must be created and

        /// caller wants to specify the specific factory to use rather than one

        /// of the injected <see cref="RepositoryFactories"/>.

        /// </param>

        /// <remarks>

        /// Looks for the requested repository in its cache, returning if found.

        /// If not found, tries to make one using <see cref="MakeRepository{T}"/>.

        /// </remarks>

        public virtual T GetRepository<T>(Func<DbContext, object> factory = null) where T : class

        {

            // Look for T dictionary cache under typeof(T).

            object repoObj;

            Repositories.TryGetValue(typeof(T), out repoObj);

            if (repoObj != null)

            {

                return (T)repoObj;

            }

 

            // Not found or null; make one, add to dictionary cache, and return it.

            return MakeRepository<T>(factory, DbContext);

        }

 

        /// <summary>

        /// Get the dictionary of repository objects, keyed by repository type.

        /// </summary>

        /// <remarks>

        /// Caller must know how to cast the repository object to a useful type.

        /// <p>This is an extension point. You can register fully made repositories here

        /// and they will be used instead of the ones this provider would otherwise create.</p>

        /// </remarks>

        protected Dictionary<Type, object> Repositories { get; private set; }

 

        /// <summary>Make a repository of type T.</summary>

        /// <typeparam name="T">Type of repository to make.</typeparam>

        /// <param name="dbContext">

        /// The <see cref="DbContext"/> with which to initialize the repository.

        /// </param>       

        /// <param name="factory">

        /// Factory with <see cref="DbContext"/> argument. Used to make the repository.

        /// If null, gets factory from <see cref="_repositoryFactories"/>.

        /// </param>

        /// <returns></returns>

        protected virtual T MakeRepository<T>(Func<DbContext, object> factory, DbContext dbContext)

        {

            var f = factory ?? _repositoryFactories.GetRepositoryFactory<T>();

            if (f == null)

            {

                throw new NotImplementedException("No factory for repository type, " + typeof(T).FullName);

            }

            var repo = (T)f(dbContext);

            Repositories[typeof(T)] = repo;

            return repo;

        }

 

        /// <summary>

        /// Set the repository for type T that this provider should return.

        /// </summary>

        /// <remarks>

        /// Plug in a custom repository if you don't want this provider to create one.

        /// Useful in testing and when developing without a backend

        /// implementation of the object returned by a repository of type T.

        /// </remarks>

        public void SetRepository<T>(T repository)

        {

            Repositories[typeof(T)] = repository;

        }

 

        /// <summary>

        /// The <see cref="RepositoryFactories"/> with which to create a new repository.

        /// </summary>

        /// <remarks>

        /// Should be initialized by constructor injection

        /// </remarks>

        private RepositoryFactories _repositoryFactories;

 

    }

 

c)       RepositoryFactories.cs

    /// <summary>

    /// A maker of Product app Repositories.

    /// </summary>

    /// <remarks>

    /// An instance of this class contains repository factory functions for different types.

    /// Each factory function takes an EF <see cref="DbContext"/> and returns

    /// a repository bound to that DbContext.

    /// <para>

    /// Designed to be a "Singleton", configured at web application start with

    /// all of the factory functions needed to create any type of repository.

    /// Should be thread-safe to use because it is configured at app start,

    /// before any request for a factory, and should be immutable thereafter.

    /// </para>

    /// </remarks>

    public class RepositoryFactories

    {

        /// <summary>

        /// Return the runtime Product app repository factory functions,

        /// each one is a factory for a repository of a particular type.

        /// </summary>

        /// <remarks>

        /// MODIFY THIS METHOD TO ADD CUSTOM FACTORY FUNCTIONS

        /// </remarks>

        private IDictionary<Type, Func<DbContext, object>> GetProductFactories()

        {

            return new Dictionary<Type, Func<DbContext, object>>

                {

                 

                };

        }

 

        /// <summary>

        /// Constructor that initializes with runtime repository factories

        /// </summary>

        public RepositoryFactories()

        {

            _repositoryFactories = GetProductFactories();

        }

 

        /// <summary>

        /// Constructor that initializes with an arbitrary collection of factories

        /// </summary>

        /// <param name="factories">

        /// The repository factory functions for this instance.

        /// </param>

        /// <remarks>

        /// This ctor is primarily useful for testing this class

        /// </remarks>

        public RepositoryFactories(IDictionary<Type, Func<DbContext, object>> factories)

        {

            _repositoryFactories = factories;

        }

 

        /// <summary>

        /// Get the repository factory function for the type.

        /// </summary>

        /// <typeparam name="T">Type serving as the repository factory lookup key.</typeparam>

        /// <returns>The repository function if found, else null.</returns>

        /// <remarks>

        /// The type parameter, T, is typically the repository type

        /// but could be any type (e.g., an entity type)

        /// </remarks>

        public Func<DbContext, object> GetRepositoryFactory<T>()

        {

 

            Func<DbContext, object> factory;

            _repositoryFactories.TryGetValue(typeof(T), out factory);

            return factory;

        }

 

        /// <summary>

        /// Get the factory for <see cref="IRepository{T}"/> where T is an entity type.

        /// </summary>

        /// <typeparam name="T">The root type of the repository, typically an entity type.</typeparam>

        /// <returns>

        /// A factory that creates the <see cref="IRepository{T}"/>, given an EF <see cref="DbContext"/>.

        /// </returns>

        /// <remarks>

        /// Looks first for a custom factory in <see cref="_repositoryFactories"/>.

        /// If not, falls back to the <see cref="DefaultEntityRepositoryFactory{T}"/>.

        /// You can substitute an alternative factory for the default one by adding

        /// a repository factory for type "T" to <see cref="_repositoryFactories"/>.

        /// </remarks>

        public Func<DbContext, object> GetRepositoryFactoryForEntityType<T>() where T : class

        {

            return GetRepositoryFactory<T>() ?? DefaultEntityRepositoryFactory<T>();

        }

 

        /// <summary>

        /// Default factory for a <see cref="IRepository{T}"/> where T is an entity.

        /// </summary>

        /// <typeparam name="T">Type of the repository's root entity</typeparam>

        protected virtual Func<DbContext, object> DefaultEntityRepositoryFactory<T>() where T : class

        {

            return dbContext => new EFRepository<T>(dbContext);

        }

 

        /// <summary>

        /// Get the dictionary of repository factory functions.

        /// </summary>

        /// <remarks>

        /// A dictionary key is a System.Type, typically a repository type.

        /// A value is a repository factory function

        /// that takes a <see cref="DbContext"/> argument and returns

        /// a repository object. Caller must know how to cast it.

        /// </remarks>

        private readonly IDictionary<Type, Func<DbContext, object>> _repositoryFactories;

 

    }

7)      Create ProductUow class that implements IProductUow in Sample.Data project:

    /// <summary>

    /// The Product "Unit of Work"

    ///     1) decouples the repos from the controllers

    ///     2) decouples the DbContext and EF from the controllers

    ///     3) manages the UoW

    /// </summary>

    /// <remarks>

    /// This class implements the "Unit of Work" pattern in which

    /// the "UoW" serves as a facade for querying and saving to the database.

    /// Querying is delegated to "repositories".

    /// Each repository serves as a container dedicated to a particular

    /// root entity type such as a <see cref="Person"/>.

    /// A repository typically exposes "Get" methods for querying and

    /// will offer add, update, and delete methods if those features are supported.

    /// The repositories rely on their parent UoW to provide the interface to the

    /// data layer (which is the EF DbContext).

    /// </remarks>

    public class ProductUow : IProductUow, IDisposable

    {

        public ProductUow(IRepositoryProvider repositoryProvider)

        {

            CreateDbContext();

 

            repositoryProvider.DbContext = DbContext;

            RepositoryProvider = repositoryProvider;

        }

 

        //  repositories

 

        public IRepository<Product> Products { get { return GetStandardRepo<Product>(); } }

        public IRepository<Category> Categories { get { return GetStandardRepo<Category>(); } }

        public IRepository<SubCategory> SubCategories { get { return GetStandardRepo<SubCategory>(); } }

 

        /// <summary>

        /// Save pending changes to the database

        /// </summary>

        public void Commit()

        {

            DbContext.SaveChanges();

        }

 

        protected void CreateDbContext()

        {

            DbContext = new ProductDbContext();

        }

 

        protected IRepositoryProvider RepositoryProvider { get; set; }

 

        private IRepository<T> GetStandardRepo<T>() where T : class

        {

            return RepositoryProvider.GetRepositoryForEntityType<T>();

        }

        private T GetRepo<T>() where T : class

        {

            return RepositoryProvider.GetRepository<T>();

        }

 

        private ProductDbContext DbContext { get; set; }

 

        #region IDisposable

 

        public void Dispose()

        {

            Dispose(true);

            GC.SuppressFinalize(this);

        }

 

        protected virtual void Dispose(bool disposing)

        {

            if (disposing)

            {

                if (DbContext != null)

                {

                    DbContext.Dispose();

                }

            }

        }

 

        #endregion

    }

8)      Now in order to use repository and unit of work in web application project (ManagingMultijQueryForm), configure Ninject via package manager console, use of following command in order to configure Ninject in an application:

a.       Install-package Ninject

b.      Install-package Ninject.MVC3

 

9)      Replace the Global.asax.cs MvcApplication class with the following:

    public class MvcApplication : NinjectHttpApplication

    {

        protected override IKernel CreateKernel()

        {

            var kernel = new StandardKernel();

 

            kernel.Bind<RepositoryFactories>().To<RepositoryFactories>()

                .InSingletonScope();

 

            kernel.Bind<IRepositoryProvider>().To<RepositoryProvider>();

            kernel.Bind<IProductUow>().To<ProductUow>();

 

            return kernel;

        }

 

        protected override void OnApplicationStarted()

        {

            AreaRegistration.RegisterAllAreas();

 

            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

            RouteConfig.RegisterRoutes(RouteTable.Routes);

        }

    }

10)   Last and final step, create a BaseController and inherit it in all (ProductController, CategoryController and SubCategoryController) controllers in order to use IProductUow:

 

a)      BaseController:

    public abstract class BaseController : Controller

    {

        protected IProductUow Uow { get; set; }

 

    }

               

b)      ProductController:

    public class ProductController : BaseController

    {

        public ProductController(IProductUow uow)

        {

            Uow = uow;

        }

 

        public ActionResult Index()

        {

            return View();

        }

 

        public ActionResult List()

        {

            return PartialView("_ProductList", Uow.Products.GetAll().ToList());

        }

 

        public PartialViewResult Add()

        {

            return PartialView("_Product");

        }

 

        [HttpPost, ValidationActionFilter]

        public PartialViewResult Add(Product model)

        {

            Uow.Products.Add(model);

            Uow.Commit();

 

            return Add();

        }

 

        public PartialViewResult Edit(int id)

        {

            return PartialView("_Product", Uow.Products.GetById(id));

        }

 

        [HttpPost, ValidationActionFilter]

        public PartialViewResult Edit(Product model)

        {

            Uow.Products.Update(model);

            Uow.Commit();

 

            return Add();

        }

 

        [HttpPost]

        public JsonResult Delete(int id)

        {

            var product = Uow.Products.GetById(id);

 

            Uow.Products.Delete(product);

            Uow.Commit();

 

            return Json(new { success = true, message = "Record deleted successfully!" }, "application/json", JsonRequestBehavior.AllowGet);

        }

    }

 

c)       CategoryController:

    public class CategoryController : BaseController

    {

        public CategoryController(IProductUow uow)

        {

            Uow = uow;

        }

 

        public ActionResult Index()

        {

            return View();

        }

 

        public JsonResult Get(int id)

        {

            var category = Uow.Categories.GetById(id);

 

            return Json(new { Id = category.CategoryID, Name = category.Name }, "application/json", JsonRequestBehavior.AllowGet);

        }

 

        public PartialViewResult List()

        {

            return PartialView("_CategoryList", Uow.Categories.GetAll().ToList());

        }

 

        [HttpPost]

        public PartialViewResult List(string s)

        {

            return PartialView("_CategoryList", Uow.Categories.GetAll().Where(m => m.Name.Contains(s)).ToList());

        }

 

        public PartialViewResult Add()

        {

            return PartialView("_Category");

        }

 

        [HttpPost, ValidationActionFilter]

        public PartialViewResult Add(Category model)

        {

            Uow.Categories.Add(model);

            Uow.Commit();

 

            return Add();

        }

 

        [HttpPost]

        public JsonResult Delete(int id)

        {

            var category = Uow.Categories.GetById(id);

 

            Uow.Categories.Delete(category);

            Uow.Commit();

 

            return Json(new { success = true, message = "Record deleted successfully!" }, "application/json", JsonRequestBehavior.AllowGet);

        }

    }

 

d)      SubCategoryController:

    public class SubCategoryController : BaseController

    {

        public SubCategoryController(IProductUow uow)

        {

            Uow = uow;

        }

 

        public ActionResult Index()

        {

            return View();

        }

 

        public JsonResult Get(int id)

        {

            var subcategory  = Uow.SubCategories.GetById(id);

 

            return Json(new { Id = subcategory.SubCategoryID, Name = subcategory.Name }, "application/json", JsonRequestBehavior.AllowGet);

        }

 

        public PartialViewResult List()

        {

            return PartialView("_SubCategoryList", Uow.SubCategories.GetAll().ToList());

        }

 

        [HttpPost]

        public PartialViewResult List(string s)

        {

            return PartialView("_SubCategoryList", Uow.SubCategories.GetAll().Where(m => m.Name.Contains(s) || m.Category.Name.Contains(s)).ToList());

        }

 

        public PartialViewResult Add()

        {

            return PartialView("_SubCategory");

        }

 

        [HttpPost, ValidationActionFilter]

        public PartialViewResult Add(SubCategory model)

        {

            Uow.SubCategories.Add(model);

            Uow.Commit();

 

            return Add();

        }

 

        [HttpPost]

        public JsonResult Delete(int id)

        {

            var subcategory = Uow.SubCategories.GetById(id);

 

            Uow.SubCategories.Delete(subcategory);

            Uow.Commit();

 

            return Json(new { success = true, message = "Record deleted successfully!" }, "application/json", JsonRequestBehavior.AllowGet);

        }

    }

Before executing an application please do replace ManagingMultijQueryForm.Models with Sample.Model in all the views and remove the reference of ManagingMultijQueryForm.Models wherever it gives error.

Now you can run and test the application I hope it works fine. You can download the source code from the link given below:

Download source code

I had taken a reference of Code Camper Spa application which is developed and thought by great John Papa.

Thanks for reading this article.

No comments: