Skip to main content

Generic Repository Pattern MVC

The good architecture is at the heart of any project. The developer is always looking for great architecture that reduces repetitive code and separates the Data Access and Business Logic. So we will be creating our generic repository using ASP.NET MVC and Entity Framework. If you don’t know about Entity Framework, please click here to get started with Entity Framework. So before getting started with repository pattern, firstly we have to understand what is the repository pattern? and why we want it?

Repository and Unit of Work Pattern


In simple words, repository means, the abstraction between your Data Access and Business Logic layers which will very useful for unit testing or test-driven development (TDD). By using repository, your system will be more loosely coupled.

In programming terms, we have to create one interface for each repository or entity. e.g. Student entity has One interface (IStudentInterface) in which all methods are declared like Insert, Update, Delete, Get and another is class (StudentRepository) which is inherited from IStudentInterface and StudentRepository will implement all the methods which are declared in Interface. When we instantiate the repository in our controller, we will use the interface so that the controller will accept a reference to any object that implements the repository interface. When the controller runs under a web server, it receives a repository that works with the Entity Framework.

When the controller runs under a unit test class, it receives a repository that works with data stored in a way that you can easily manipulate for testing, such as an in-memory collection. So we can supply fake repository in unit testing.

If you want to see the complete implementation, please refer to the following link:


Disadvantage


Each time we have to create Repository for each entity, it results in redundant code.

Using the Code


Now we need only a data access class which accepts any entity and performs required operation, e.g. CRUD. After studying lots of articles, theories and sample code, I got one very good reference of Generic Repository Pattern.

My code is heavily based on the Huy Nguyen’s Blog. Please refer to the following links:


I have changed a bit of code and added to new class library project as well as I added some common function which required to each project. Now I can use this library in any project. Following is the folder structure.

Mayur.DAL – Class library project with generic repository and common functions.

  • Core – Folder

    • GlobalCommonHelper.cs – An abstract class which contents all common function required to each project
  • Repository – Folder
    • IRepository.cs – Interface for generic repository
    • Repository.cs – Generic repository class inherited from IRepository. All methods are implemented in it.
    • IUnitOfWork.cs – Interface for unit of work class.
    • UnitOfWork.cs – Implemented SaveChanges() methods for Entity Framework . The unit of work class is very important when we execute any transitional command to the database like Insert, Update, Delete the entity framework not commit to database until Savechanges() method calls.

Mayur.Web – MVC project

  • Controller – Folder

    • HomeController.cs – Home controller with Index, Create, Edit, Delete ActionResult
  • Core – Folder
    • CommonHelper.cs – Inherited from Mayur.DAL.Core.GlobalCommonHelper.cs which contents all common methods related to MVC project
  • Model – Folder
    • Student.csStudent Model representing studnet table
  • Views – Folder
    • Index.chtml – Display All student html
    • Create.chtml – Create new student html
    • Edit.cshtml – Update student info html
    • Delete.cshtml – Delete student info html

Lets understand briefly each file in Mayur.DAL:

Repository Folder: In this folder, all the Data Access logic is present. There are 4 files, 2 are Interfaces and 2 are classes which inherited from respective Interface.

1. IRepository Interface

public interface IRepository : IDisposable
    {
        /// <summary>
        ///     Gets the unit of work.
        /// </summary>
        /// <value>The unit of work.</value>
        IUnitOfWork UnitOfWork { get; }
 
        /// <summary>
        ///     Gets entity by key.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="keyValue">The key value.</param>
        /// <returns></returns>
        TEntity GetByKey<TEntity>(object keyValue) where TEntity : class;
 
        /// <summary>
        ///     Gets the query.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <returns></returns>
        IQueryable<TEntity> GetQuery<TEntity>() where TEntity : class;
 
        /// <summary>
        ///     Gets the query.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="predicate">The predicate.</param>
        /// <returns></returns>
        IQueryable<TEntity> GetQuery<TEntity>
        (Expression<Func<TEntity, bool>> predicate) where TEntity : class;
 
 
        /// <summary>
        ///     Gets all.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <returns></returns>
        IEnumerable<TEntity> GetAll<TEntity>() where TEntity : class;
 
        /// <summary>
        ///     Gets the specified order by.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <typeparam name="TOrderBy">The type of the order by.</typeparam>
        /// <param name="orderBy">The order by.</param>
        /// <param name="pageIndex">Index of the page.</param>
        /// <param name="pageSize">Size of the page.</param>
        /// <param name="sortOrder">The sort order.</param>
        /// <returns></returns>
        IEnumerable<TEntity> Get<TEntity, 
        TOrderBy>(Expression<Func<TEntity, TOrderBy>> orderBy, int pageIndex,
            int pageSize, SortOrder sortOrder = SortOrder.Ascending) where TEntity : class;
 
        /// <summary>
        ///     Gets the specified criteria.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <typeparam name="TOrderBy">The type of the order by.</typeparam>
        /// <param name="criteria">The criteria.</param>
        /// <param name="orderBy">The order by.</param>
        /// <param name="pageIndex">Index of the page.</param>
        /// <param name="pageSize">Size of the page.</param>
        /// <param name="sortOrder">The sort order.</param>
        /// <returns></returns>
        IEnumerable<TEntity> Get<TEntity, 
        TOrderBy>(Expression<Func<TEntity, bool>> criteria,
            Expression<Func<TEntity, TOrderBy>> orderBy, int pageIndex, int pageSize,
            SortOrder sortOrder = SortOrder.Ascending) where TEntity : class;
 
 
        /// <summary>
        ///     Gets one entity based on matching criteria
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="criteria">The criteria.</param>
        /// <returns></returns>
        TEntity Single<TEntity>(Expression<Func<TEntity, 
        bool>> criteria) where TEntity : class;
 
 
 
        /// <summary>
        ///     Firsts the specified predicate.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="predicate">The predicate.</param>
        /// <returns></returns>
        TEntity First<TEntity>(Expression<Func<TEntity, 
        bool>> predicate) where TEntity : class;
 
        /// <summary>
        ///     Finds entities based on provided criteria.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="criteria">The criteria.</param>
        /// <returns></returns>
        IEnumerable<TEntity> Find<TEntity>
        (Expression<Func<TEntity, bool>> criteria) where TEntity : class;
 
 
 
        /// <summary>
        ///     Finds one entity based on provided criteria.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="criteria">The criteria.</param>
        /// <returns></returns>
        TEntity FindOne<TEntity>(Expression<Func<TEntity, 
        bool>> criteria) where TEntity : class;
 
 
 
        /// <summary>
        ///     Counts the specified entities.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <returns></returns>
        int Count<TEntity>() where TEntity : class;
 
        /// <summary>
        ///     Counts entities with the specified criteria.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="criteria">The criteria.</param>
        /// <returns></returns>
        int Count<TEntity>(Expression<Func<TEntity, 
        bool>> criteria) where TEntity : class;
 
 
 
        /// <summary>
        ///     Adds the specified entity.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="entity">The entity.</param>
        void Add<TEntity>(TEntity entity) where TEntity : class;
 
        /// <summary>
        ///     Attaches the specified entity.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="entity">The entity.</param>
        void Attach<TEntity>(TEntity entity) where TEntity : class;
 
        /// <summary>
        ///     Updates changes of the existing entity.
        ///     The caller must later call SaveChanges() 
        ///     on the repository explicitly to save the entity to database
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="entity">The entity.</param>
        void Update<TEntity>(TEntity entity) where TEntity : class;
 
        /// <summary>
        ///     Deletes the specified entity.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="entity">The entity.</param>
        void Delete<TEntity>(TEntity entity) where TEntity : class;
 
        /// <summary>
        ///     Deletes one or many entities matching the specified criteria
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="criteria">The criteria.</param>
        void Delete<TEntity>(Expression<Func<TEntity, 
        bool>> criteria) where TEntity : class;
 
        /// <summary>
        ///     Deletes entities which satisfy specificatiion
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="criteria">The criteria.</param>
        //void Delete<TEntity>
        (ISpecification<TEntity> criteria) where TEntity : class;
    }

2. Repository Class

/// <summary>
    ///     Generic repository Class
    /// </summary>
    public partial class Repository : IRepository, IDisposable
    {
        //Private Variables
        private bool bDisposed;
        private DbContext context;
        private IUnitOfWork unitOfWork;
         
        #region Contructor Logic
 
        /// <summary>
        /// Initializes a new instance of the 
        /// <see cref="Repository<TEntity>"/> class.
        /// </summary>
        public Repository()
        {
 
        }
 
        /// <summary>
        ///     Initializes a new instance of the 
        /// <see cref="Repository<TEntity>" /> class.
        /// </summary>
        /// <param name="context">The context.</param>
        public Repository(DbContext contextObj)
        {
            if (contextObj == null)
                throw new ArgumentNullException("context");
            this.context = contextObj;
        }
 
        public Repository(ObjectContext contextObj)
        {
            if (contextObj == null)
                throw new ArgumentNullException("context");
            context = new DbContext(contextObj, true);
        }
 
        public void Dispose()
        {
            Close();
        }
 
        #endregion
 
        #region Properties
 
        //DbContext Property
        protected DbContext DbContext
        {
            get
            {
                if (context == null)
                    throw new ArgumentNullException("context");
 
                return context;
            }
        }
 
        //Unit of Work Property
        public IUnitOfWork UnitOfWork
        {
            get
            {
                if (unitOfWork == null)
                {
                    unitOfWork = new UnitOfWork(DbContext);
                }
                return unitOfWork;
            }
        }
 
        #endregion
         
        #region Data Display Methods
 
        //Helper Method tp create Query [IQuerable]
 
        public TEntity GetByKey<TEntity>(object keyValue) where TEntity : class
        {
            EntityKey key = GetEntityKey<TEntity>(keyValue);
 
            object originalItem;
            if (((IObjectContextAdapter)DbContext).
            ObjectContext.TryGetObjectByKey(key, out originalItem))
            {
                return (TEntity)originalItem;
            }
 
            return default(TEntity);
        }
 
        public IQueryable<TEntity> GetQuery<TEntity>() where TEntity : class
        {
            string entityName = GetEntityName<TEntity>();
            return ((IObjectContextAdapter)DbContext).
            ObjectContext.CreateQuery<TEntity>(entityName);
        }
 
        public IQueryable<TEntity> GetQuery<TEntity>
        (Expression<Func<TEntity, bool>> predicate) where TEntity : class
        {
            return GetQuery<TEntity>().Where(predicate);
        }
 
 
        //All Readonly Display or fetch data methods.
        public IEnumerable<TEntity> GetAll<TEntity>() where TEntity : class
        {
            return GetQuery<TEntity>().AsEnumerable();
        }
 
        public IEnumerable<TEntity> Get<TEntity, TOrderBy>
        (Expression<Func<TEntity, TOrderBy>> orderBy, int pageIndex,
            int pageSize, SortOrder sortOrder = SortOrder.Ascending) where TEntity : class
        {
            if (sortOrder == SortOrder.Ascending)
            {
                return GetQuery<TEntity>()
                    .OrderBy(orderBy)
                    .Skip((pageIndex - 1) * pageSize)
                    .Take(pageSize)
                    .AsEnumerable();
            }
            return
                GetQuery<TEntity>()
                    .OrderByDescending(orderBy)
                    .Skip((pageIndex - 1) * pageSize)
                    .Take(pageSize)
                    .AsEnumerable();
        }
 
        public IEnumerable<TEntity> Get<TEntity, 
        TOrderBy>(Expression<Func<TEntity, bool>> criteria,
            Expression<Func<TEntity, TOrderBy>> orderBy, int pageIndex, int pageSize,
            SortOrder sortOrder = SortOrder.Ascending) where TEntity : class
        {
            if (sortOrder == SortOrder.Ascending)
            {
                return GetQuery(criteria).
                    OrderBy(orderBy).
                    Skip((pageIndex - 1) * pageSize).
                    Take(pageSize)
                    .AsEnumerable();
            }
            return
                GetQuery(criteria)
                    .OrderByDescending(orderBy)
                    .Skip((pageIndex - 1) * pageSize)
                    .Take(pageSize)
                    .AsEnumerable();
        }
 
        public TEntity Single<TEntity>
        (Expression<Func<TEntity, bool>> criteria) where TEntity : class
        {
            return GetQuery<TEntity>().Single<TEntity>(criteria);
        }
 
        public TEntity First<TEntity>
        (Expression<Func<TEntity, bool>> predicate) where TEntity : class
        {
            return GetQuery<TEntity>().First(predicate);
        }
 
        public IEnumerable<TEntity> Find<TEntity>
        (Expression<Func<TEntity, bool>> criteria) where TEntity : class
        {
            return GetQuery<TEntity>().Where(criteria);
        }
 
        public TEntity FindOne<TEntity>
        (Expression<Func<TEntity, bool>> criteria) where TEntity : class
        {
            return GetQuery<TEntity>().Where(criteria).FirstOrDefault();
        }
 
        public int Count<TEntity>() where TEntity : class
        {
            return GetQuery<TEntity>().Count();
        }
 
        public int Count<TEntity>
        (Expression<Func<TEntity, bool>> criteria) where TEntity : class
        {
            return GetQuery<TEntity>().Count(criteria);
        }
 
        #endregion
         
        #region Data Transactional Methods
 
        public void Add<TEntity>(TEntity entity) where TEntity : class
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }
            DbContext.Set<TEntity>().Add(entity);
        }
 
        public void Attach<TEntity>(TEntity entity) where TEntity : class
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }
 
            DbContext.Set<TEntity>().Attach(entity);
        }
 
        public void Update<TEntity>(TEntity entity) where TEntity : class
        {
            string fqen = GetEntityName<TEntity>();
 
            object originalItem;
            EntityKey key = 
            ((IObjectContextAdapter)DbContext).ObjectContext.CreateEntityKey(fqen, entity);
            if (((IObjectContextAdapter)DbContext).ObjectContext.TryGetObjectByKey
            (key, out originalItem))
            {
                ((IObjectContextAdapter)DbContext).ObjectContext.ApplyCurrentValues
                (key.EntitySetName, entity);
            }
        }
 
        public void Delete<TEntity>(TEntity entity) where TEntity : class
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }
            DbContext.Set<TEntity>().Remove(entity);
        }
 
        public void Delete<TEntity>(Expression<Func<TEntity, 
        bool>> criteria) where TEntity : class
        {
            IEnumerable<TEntity> records = Find(criteria);
 
            foreach (TEntity record in records)
            {
                Delete(record);
            }
        }
 
        #endregion
 
        #region Internal Processing Private Methods
 
        private EntityKey GetEntityKey<TEntity>(object keyValue) where TEntity : class
        {
            string entitySetName = GetEntityName<TEntity>();
            ObjectSet<TEntity> objectSet = 
            ((IObjectContextAdapter)DbContext).ObjectContext.CreateObjectSet<TEntity>();
            string keyPropertyName = objectSet.EntitySet.ElementType.KeyMembers[0].ToString();
            var entityKey = new EntityKey
            (entitySetName, new[] { new EntityKeyMember(keyPropertyName, keyValue) });
            return entityKey;
        }
 
        private string GetEntityName<TEntity>() where TEntity : class
        {
            // Thanks to Kamyar Paykhan -  
            // http://huyrua.wordpress.com/2011/04/13/
            // entity-framework-4-poco-repository-and-specification-pattern-upgraded-to-ef-4-1/
            // #comment-688
            string entitySetName = ((IObjectContextAdapter)DbContext).ObjectContext
                .MetadataWorkspace
                .GetEntityContainer(((IObjectContextAdapter)DbContext).
                    ObjectContext.DefaultContainerName,
                    DataSpace.CSpace)
                .BaseEntitySets.Where(bes => bes.ElementType.Name == typeof(TEntity).Name).First().Name;
            return string.Format("{0}.{1}", 
            ((IObjectContextAdapter)DbContext).ObjectContext.DefaultContainerName,
                entitySetName);
        }
 
        private string RemoveAccent(string txt)
        {
            byte[] bytes = System.Text.Encoding.GetEncoding("Cyrillic").GetBytes(txt);
            return System.Text.Encoding.ASCII.GetString(bytes);
        }
 
        private bool IsValidTag(string tag, string tags)
        {
            string[] allowedTags = tags.Split(',');
            if (tag.IndexOf("javascript") >= 0) return false;
            if (tag.IndexOf("vbscript") >= 0) return false;
            if (tag.IndexOf("onclick") >= 0) return false;
 
            var endchars = new char[] { ' ', '>', '/', '\t' };
 
            int pos = tag.IndexOfAny(endchars, 1);
            if (pos > 0) tag = tag.Substring(0, pos);
            if (tag[0] == '/') tag = tag.Substring(1);
 
            foreach (string aTag in allowedTags)
            {
                if (tag == aTag) return true;
            }
 
            return false;
        }
 
        #endregion          
 
        #region Disposing Methods
 
        protected void Dispose(bool bDisposing)
        {
            if (!bDisposed)
            {
                if (bDisposing)
                {
                    if (null != context)
                    {
                        context.Dispose();
                    }
                }
                bDisposed = true;
            }
        }
 
        public void Close()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
 
        #endregion
    }
 }

3. IUnitOfWork Interface

public interface IUnitOfWork : IDisposable
{
    void SaveChanges();
}

4. UnitOfWork Class

internal class UnitOfWork : IUnitOfWork
    {
        private readonly DbContext _dbContext;
 
        public UnitOfWork(DbContext context)
        {
            _dbContext = context;
        }  
 
        public void SaveChanges()
        {
            ((IObjectContextAdapter)_dbContext).ObjectContext.SaveChanges();
        } 
 
        #region Implementation of IDisposable
 
        private bool _disposed;
 
        /// <summary>
        ///     Performs application-defined tasks associated with freeing, 
        ///     releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
 
        /// <summary>
        ///     Disposes off the managed and unmanaged resources used.
        /// </summary>
        /// <param name="disposing"></param>
        private void Dispose(bool disposing)
        {
            if (!disposing)
                return;
 
            if (_disposed)
                return;
 
            _disposed = true;
        }
 
        #endregion        
    }

Now in Mayur.DAL.Core folder, there is one abstract class with all common functions required for each project. If you have any new functions which we required in each project, please suggest in the comments.

5. Mayur.DAL.Core.GlobalCommonHelper.cs Class

abstract public class GlobalCommonHelper
    {
        #region General Methods
 
        /// <summary>
        /// Take any string and encrypt it using SHA1 then
        /// return the encrypted data
        /// </summary>
        /// <param name="data">input text you will enterd to encrypt it</param>
        /// <returns>return the encrypted text as hexadecimal string</returns>
        public string GetSHA1HashData(string data)
        {
            //create new instance of md5
            SHA1 sha1 = SHA1.Create();
 
            //convert the input text to array of bytes
            byte[] hashData = sha1.ComputeHash(Encoding.Default.GetBytes(data));
 
            //create new instance of StringBuilder to save hashed data
            StringBuilder returnValue = new StringBuilder();
 
            //loop for each byte and add it to StringBuilder
            for (int i = 0; i < hashData.Length; i++)
            {
                returnValue.Append(hashData[i].ToString());
            }
 
            // return hexadecimal string
            return returnValue.ToString();
        }
 
        /// <summary>
        /// Creates a slug url from string .
        /// </summary>
        /// <param name="phrase"></param>
        /// <returns></returns>
        public string GetSlugURLFromString(string phrase)
        {
            string str = RemoveAccent(phrase).ToLower();
            // invalid chars          
            str = Regex.Replace(str, @"[^a-z0-9\s-]", "");
            // convert multiple spaces into one space  
            str = Regex.Replace(str, @"\s+", " ").Trim();
            // cut and trim
            str = str.Substring(0, str.Length <= 45 ? str.Length : 45).Trim();
            str = Regex.Replace(str, @"\s", "-"); // hyphens  
            return str;
        }
 
        /// <summary>
        /// Delete file by specified path.
        /// </summary>
        /// <param name="path">path of file.</param>
        public void DeleteTargetFile(string path)
        {
            if (File.Exists(path))
            {
                File.SetAttributes(path, FileAttributes.Normal);
                File.Delete(path);
            }
        }
 
        /// <summary>
        /// Sent email to target email address with attachment.
        /// </summary>
        /// <param name="toEmail">Email addresses of 
        /// one or multiple receipients semi colon (;) separated values.</param>
        /// <param name="subject">Email subject</param>
        /// <param name="body">Email body</param>
        /// <returns>True | False</returns>
        public bool SendEmailToTarget(string toEmail, string subject, string body)
        {
 
            bool success = false;
            try
            {
                SmtpClient SmtpServer = new SmtpClient();
                MailMessage mail = new MailMessage();
 
                SmtpServer.Credentials = new NetworkCredential(
                    Convert.ToString(ConfigurationManager.AppSettings["fromEmail"]),
                    Convert.ToString(ConfigurationManager.AppSettings["fromPassword"]));
 
                SmtpServer.Host = Convert.ToString
                (ConfigurationManager.AppSettings["hostName"]);
                SmtpServer.Port = Convert.ToInt32
                (ConfigurationManager.AppSettings["portNumber"]);
 
                if (Convert.ToBoolean
                (ConfigurationManager.AppSettings["isEnableSSL"]) == true)
                    SmtpServer.EnableSsl = true;
 
                mail.From = new MailAddress(Convert.ToString
                (ConfigurationManager.AppSettings["senderName"]));
 
                string[] multiEmails = toEmail.Split(';');
                foreach (string email in multiEmails)
                {
                    mail.To.Add(email);
                }
 
                mail.Subject = subject;
                mail.IsBodyHtml = true;
                mail.Body = body;
                SmtpServer.Send(mail);
                mail.Dispose();
                success = true;
            }
            catch (Exception)
            {
                success = false;
            }
            return success;
        }
 
        /// <summary>
        /// Sent email to target email address with attachment.
        /// </summary>
        /// <param name="toEmail">Email addresses of 
        /// one or multiple receipients semi colon (;) separated values.</param>
        /// <param name="subject">Email subject</param>
        /// <param name="body">Email body</param>
        /// <param name="body">Email attachment file path</param>
        /// <returns>True | False</returns>
        public bool SendEmailToTarget(string toEmail, string subject, string body, string attachmentPath)
        {
 
            bool success = false;
            try
            {
                SmtpClient SmtpServer = new SmtpClient();
                MailMessage mail = new MailMessage();
 
                SmtpServer.Credentials = new NetworkCredential(
                    Convert.ToString(ConfigurationManager.AppSettings["fromEmail"]),
                    Convert.ToString(ConfigurationManager.AppSettings["fromPassword"]));
 
                SmtpServer.Host = Convert.ToString
                (ConfigurationManager.AppSettings["hostName"]);
                SmtpServer.Port = Convert.ToInt32
                (ConfigurationManager.AppSettings["portNumber"]);
 
                if (Convert.ToBoolean(ConfigurationManager.AppSettings["isEnableSSL"]) == true)
                    SmtpServer.EnableSsl = true;
 
                mail.From = new MailAddress(Convert.ToString
                (ConfigurationManager.AppSettings["senderName"]));
 
                string[] multiEmails = toEmail.Split(';');
                foreach (string email in multiEmails)
                {
                    mail.To.Add(email);
                }
 
                Attachment attachment;
                attachment = new System.Net.Mail.Attachment(attachmentPath);
                mail.Attachments.Add(attachment);
 
                mail.Subject = subject;
                mail.IsBodyHtml = true;
                mail.Body = body;
                SmtpServer.Send(mail);
                mail.Dispose();
                success = true;
            }
            catch (Exception)
            {
                success = false;
            }
            return success;
        }
 
        /// <summary>
        /// Strips tags
        /// </summary>
        /// <param name="text">Text</param>
        /// <returns>Formatted text</returns>
        public string RemoveHtmlFromString(string text)
        {
            if (String.IsNullOrEmpty(text))
                return string.Empty;
 
            text = Regex.Replace(text, @"(>)(\r|\n)*(<)", "><");
            text = Regex.Replace(text, "(<[^>]*>)([^<]*)", "$2");
            text = Regex.Replace(text, "(&#x?[0-9]{2,4};|"|&| 
            |<|>|€|©|®|‰|‡|†|‹|
            ›|„|”|“|‚|’|‘|—|
            –|‏|‎|‍|‌| | | |˜|
            ˆ|Ÿ|š|Š)", "@");
 
            return text;
        }
 
        /// <summary>
        /// Verifies that a string is in valid e-mail format
        /// </summary>
        /// <param name="email">Email to verify</param>
        /// <returns>true if the string is a valid e-mail address and false if it's not</returns>
        public bool IsValidEmail(string email)
        {
            if (String.IsNullOrEmpty(email))
                return false;
 
            email = email.Trim();
            var result = Regex.IsMatch(email, "^(?:[\\w\\!\\#\\$\\%\\&\\
            '\\*\\+\\-\\/\\=\\?\\^\\`\\{\\|\\}\\~]+\\.)*[\\w\\!\\#\\$\\%\\&\\
            '\\*\\+\\-\\/\\=\\?\\^\\`\\{\\|\\}\\~]+@(?:(?:(?:[a-zA-Z0-9]
            (?:[a-zA-Z0-9\\-](?!\\.)){0,61}[a-zA-Z0-9]?\\.)+[a-zA-Z0-9]
            (?:[a-zA-Z0-9\\-](?!$)){0,61}[a-zA-Z0-9]?)|(?:\\[(?:(?:[01]?\\d{1,2}|2[0-4]
            \\d|25[0-5])\\.){3}(?:[01]?\\d{1,2}|2[0-4]\\d|25[0-5])\\]))$", RegexOptions.IgnoreCase);
            return result;
        }
 
        /// <summary>
        /// Returns Allowed HTML only.
        /// </summary>
        /// <param name="text">Text</param>
        /// <returns>Allowed HTML</returns>
        public string EnsureOnlyAllowedHtml(string text)
        {
            if (String.IsNullOrEmpty(text))
                return string.Empty;
 
            const string allowedTags = "br,hr,b,i,u,a,div,ol,ul,li,blockquote,img,span,p,em," +
                                        "strong,font,pre,h1,h2,h3,h4,h5,h6,address,cite";
 
            var m = Regex.Matches(text, "<.*?>", RegexOptions.IgnoreCase);
            for (int i = m.Count - 1; i >= 0; i--)
            {
                string tag = text.Substring(m[i].Index + 1, m[i].Length - 1).Trim().ToLower();
 
                if (!IsValidTag(tag, allowedTags))
                {
                    text = text.Remove(m[i].Index, m[i].Length);
                }
            }
 
            return text;
        }
 
        #endregion
 
        #region Internal Processing Private Methods
 
        private string RemoveAccent(string txt)
        {
            byte[] bytes = System.Text.Encoding.GetEncoding("Cyrillic").GetBytes(txt);
            return System.Text.Encoding.ASCII.GetString(bytes);
        }
 
        private bool IsValidTag(string tag, string tags)
        {
            string[] allowedTags = tags.Split(',');
            if (tag.IndexOf("javascript") >= 0) return false;
            if (tag.IndexOf("vbscript") >= 0) return false;
            if (tag.IndexOf("onclick") >= 0) return false;
 
            var endchars = new char[] { ' ', '>', '/', '\t' };
 
            int pos = tag.IndexOfAny(endchars, 1);
            if (pos > 0) tag = tag.Substring(0, pos);
            if (tag[0] == '/') tag = tag.Substring(1);
 
            foreach (string aTag in allowedTags)
            {
                if (tag == aTag) return true;
            }
 
            return false;
        }
 
        #endregion
 
    }

Now our Generic repository is ready with inbuilt common functions. Now we can see how to use them in controller. Suppose we have Students model in which studentID, name, rollNo columns. Following is the code for HomeController.

  1. Before we proceed, we are using code first approach and following is our DbContext class:

    public partial class MyFirstDbContext : DbContext
    {
        public MyFirstDbContext()
        : base("name=MyFirstDbContext")
        {
            Database.SetInitializer<MyFirstDbContext>(null);
        }
     
        public virtual DbSet<Students> Students { get; set; }
     
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
     
        }
    }
  2. We have created an abstract class in out Data Access Layer which contains Global common function means almost in each project we required that function. The class is an abstract class so we cannot create an instance of it . So we create new CommonHelper.cs Class in Our Web project which is inherited from Abstract class and we can implement project-specific common functions here.
    public class CommonHelper : GlobalCommonHelper
    {
         public int PageSize = 25;
         //Some common functions. Only Project-specific.     
    }
  3. Now we can see how we use repository in our HomeController. The HomeController is as follows:
    //Constructor
    public HomeController()
    {
          IRepository repository = new Repository(new MyFirstDbContex);
          CommonHelper helper = new CommonHelper();
    }

    1. Index.cshtml represents the view of all Students in table format. So ActionResult is as follows:

      public ActionResult Index()
      {
            return View(repository.GetAll<Students>());
      }
    2. Create.cshtml creates new Students record means it inserts new record in db.
      public ActionResult Create()
      {
            return View();
      }
       
      [HttpPost]
      public ActionResult Create(Students studPost)
      {
           if(ModelState.IsValid)
           {
                repository.Add<Students>(studPost);
                repository.UnitOfWork.SaveChanges();
           }
      }
    3. Edit.cshtml represents the edit view in which we can modify the records.
      public ActionResult Edit(int id=0)
      {
            if(id==0)
                return HttpNotFound();
             
             Students stud = repository.FindOne<Students>(x=>x.studentID == id);
            return View(stud);
      }
       
      [HttpPost]
      public ActionResult Edit(Students studPost)
      {
           if(ModelState.IsValid)
           {
                repository.Update<Students>(studPost);
                repository.UnitOfWork.SaveChanges();
           }
      }
    4. And the last one is Delete as follows:
      [HttpPost]
      public ActionResult Delete(int id=0)
      {
                if(id==0)
                    return HttpNotFound();
       
                Students stud = repository.FindOne<Students>(x=>x.studentID == id);
                if(stud == null)
                    return HttpNotFound();
       
                repository.Delete<Students>(stud);
                repository.UnitOfWork.SaveChanges();
      }

I need more suggestions and improvements from you. Please comment.


Revisions


  • 31/05/2015: Article published
  • 30/04/2016: Article Updated fixed some constructor error as per the "Irene Troupansky" Suggestions.

Comments

Popular posts from this blog

दान धर्माची बदललेली परिभाषा

नमस्कार! बरेच वेळा मनात विचार येतात पण लिहिण्याचा प्रयत्न पहिल्यांदाच करत आहे. तरी चूक भूल माफी असावी. आजकाल Whatsapp आणि Facebook यांच्यामुळे जग जवळ आले आहे, पण सगळ्याच गोष्टी share करण्याचा जणु छंदच लोकांना जडला आहे. अर्थात थोड्याफार प्रमाणात मी पण share करत असतो पण अगदी थोडक्या प्रमाणात. आता कोणी दानधर्म करत असेल तर तो पण यावर सर्रास Share केला जातो, मुळात दान याची वाख्याच लोक विसरत चालले आहे. याचीसुद्धा मार्केटिंग होऊ लागली आहे. मुळात दान हे निस्वार्थ भावनेने केले पाहिजे (असे दान ज्याला परताव्याची इच्छा नसते), जेव्हा लोक आपण दान करतो असा दाखवायचा प्रयत्न करतात मग ते facebook share असो किवां whatsapp status,post किवां इतर कोणतेही माध्यम याचा अर्थ असा कि दान करताना या लोकांनी मला प्रसिद्धी मिळेल किवां मी किती दानशुर आहे हे दाखवण्याची भावना मनात ठेवून केलेले दान होय. अशी परताव्याची भावना मनात ठेवून केलेले दान हे दान नसून व्यवहाराच नाही का? व्यवहारात जस आपण पैसे देऊन त्या बदल्यात वस्तू,सेवा खरेदी करतो, तसेच परताव्याचा विचार करून केलेले दान म्हणजे व्यवहाराच. असो माझे विचार

How To Create Custom HTML Helper in ASP.NET MVC? Here Is The Way.

In this article, I will explain how to create a custom HTML helper as per your requirement. If you know the MVC and Helpers already, you can skip the next paragraph and if you don't know, here is an explanation about helpers. What are HTML Helpers in MVC? An HTML helper is a method that is used to render the specified html content in View. It can be implemented as an extension method. If you know the ASP.NET webforms, you might know the concept of web controls. e.g. <asp:TextBox /><asp:label /> If you use these controls in web form on browsers, they will converted to their equivalent HTML controls like TextBox will be <input type="text" /> and label will be <span></span> HTML helpers methods are the same as web controls it allows to render appropriate HTML in view. Let's take an example of how HTML helper looks like: @Html.TextBox("Myname","Mayur Lohite") This HTML helper will render the following HTML

Why Interface For Decoupled System? A Note On How To Design Decoupled System in ASP.NET MVC

An Interface At first, interfaces came into focus because there was no multiple inheritance supported by C#, meaning you could not inherit from multiple classes, but you could implement multiple interfaces. The interfaces are grouping of object in terms of behavior. An interface contains only signatures. There is no implementation, only the signatures of the functionality the interface provides. An interface can contain signatures of methods, properties, indexers & events. Interface doesn't do anything like classes and abstract classes, it just defines what the class will perform if some class inherits it. An interface can also be inherited from another interface. If we take an example of USB (Universal Serial Bus), it's an interface which has signature of Connection functionality. The USB interface only knows I have to connect with Desktop Computer or laptop or anything, but it does not know what implementation will come to connection. It may be Pen d