This article will demonstrate us about best practices which should be used when working with Asp.Net MVC application. We always try to make Asp.Net MVC application using best practices but don't know exactly where we can implement best things. So, in this demonstration, you will see best practices which should be implemented when creating MVC application. 

Asp.Net MVC

Isolate Components

Asp.Net MVC application contains several components like Model, Controller, View, Data Access Logic, Repository Logic, Service Layer. So, best practice is that always isolate with different solutions. It makes life easy when working with different components.

App Solution

Use View Model

When working with enterprise level application in Asp.Net MVC, don't work with Entity [Model] directly. We should create ViewModels which will strongly bind with Views. ViewModel is a class same as Model class but contains some extra properties which required only for business process.

Note: ViewModel should always be in different folder.

ViewModel

 

Always Dispose Context Object

Generally in Asp.Net MVC we prefer to work with Custom DataContext Class which inherited DbContext. But when we perform database operations like Create, Read, Update and Delete through this context object. So, it is necessary to dispose the context object after process. 

To do this, create a class which implement IDisposable interface. 

public abstract class DefaultDisposable : IDisposable
{
        protected readonly NextProgrammingDataContext context;

        private bool _disposed;
        private readonly object _disposeLock = new object();
        protected DefaultDisposable()
        {
            context = new NextProgrammingDataContext();
        }
        public void Dispose()
        {
            Dispose(true);
        }
        protected virtual void Dispose(bool disposing)
        {
            lock (_disposeLock)
            {
                if (!_disposed)
                {
                    if (disposing)
                    {
                        context.Dispose();
                    }

                    _disposed = true;
                }
            }
        }
}

 

And Inherit this class with our Repository Class where context object will be destroy after completing the process.

public class CategoryRepository: DefaultDisposable, ICategoryRepository
{
        public int AddNewCategory(Category categoryEntity)
        {
            int categoryId = 0;
            if (categoryEntity != null)
            {
                if (CheckCategoryExists(categoryEntity.CategoryName) > 0)
                {
                    categoryId = CheckCategoryExists(categoryEntity.CategoryName);
                }
                else
                {
                    context.Categories.Add(categoryEntity);
                    context.SaveChanges();
                    categoryId = categoryEntity.CategoryId;
                }               
            }

            return categoryId;
        }
}

 

Use Caching through Web.Config

Caching is an important feature when working with Web Development. It reduces load time when our website uses Caching feature. We can implement Caching in Asp.Net MVC using OutputCache attribute. It is part of Action Filter. OutputCacheAttribute class inherite ActionFilterAttribute class.

Output Cache

To implement Output Cache, just put the OutputCache attribute on Controller or Action level as following line of code showing.

OutputCache(CacheProfile = "MyCache")]
public ActionResult Index(int? pageNumber)
{
   int page = pageNumber ?? 1;
   return View();
}

 

Above code shows that we are using OutputCache attribute with action level and passing the CacheProfile. So, what CacheProfile is. Basically it is best practice to implement cache through Web.Config file, we can create n numbers of Cache Profile in Web.Config and use it as per requirment as following code.

<system.web>
    <caching>
      <outputCacheSettings>
        <outputCacheProfiles>
          <add name="MyCache" duration="100000" varyByParam="none" location="Server"/>
        </outputCacheProfiles>
      </outputCacheSettings>
    </caching>
</system.web>

 

Use BaseController

It is recommended to use Base Controller with our controller and this Base Controller will inherit Controller class directly. It provides isolation space between our controller [InterviewController] and Controller. Using Base Controller we can write common logic which could be shared by all controllers.

 public class BaseController : Controller
 {
        protected virtual LoginPrincipal LoggedUser
        {
            get { return HttpContext.User as LoginPrincipal; }
        }

        protected int GetUserId()
        {
            int userId = -1;
            if (Request.IsAuthenticated)
            {
                userId = LoggedUser.UserId;
            }
            return userId;
        }
 }

And use it as following.

public class InterviewController : BaseController

 

Use Dependency Injection

It always recommended to use Dependency Injection with Asp.Net MVC application. And on the runtime, inject class dependencies. For more infor refer my article How to use Dependency Injection with Asp.Net MVC application.

public class InterviewController : BaseController
{
        private const int pageSize = 10;
        private readonly IInterviewPostRepository _interviewPostRepository;
        private readonly IInterviewCategoryRepository _interviewCategoryRepository;
        private readonly ICommentsRepository _commentsRepository;
        private readonly IUserRepository _userRepository;

        public InterviewController(IInterviewPostRepository interviewPostRepository, IInterviewCategoryRepository interviewCategoryRepository,  ICommentsRepository commentsRepository, IUserRepository userRepository)
        {
            _interviewPostRepository = interviewPostRepository;
            _interviewCategoryRepository = interviewCategoryRepository;
            _commentsRepository = commentsRepository;
            _userRepository=userRepository;
        }

        public ActionResult Index(int? pageNumber)
        {
          return View();
        }

}

There are different ways to use Dependency Injection, we are using Ninject with this demonstration.

 public class NinjectBindings : NinjectModule
 {
        public override void Load()
        {
            Bind<IUserRepository>().To<UserRepository>();           
            Bind<ICommentsRepository>().To<CommentsRepository>();           
            Bind<IInterviewCategoryRepository>().To<InterviewCategoryRepository>();
            Bind<IInterviewPostRepository>().To<InterviewPostRepository>();        
        }
 }

 

Strongly Type View

Best practice when working with View and passing data from controller using data access logic to use Strongly Type View and which map with a ViewModel directly.

@model DotnetTutorial.Data.ViewModel.ContactUsViewModel
@{
    ViewBag.Title = "Contact Us - DotNet Tutorial";
    Layout = "~/Views/Shared/_LayoutBase.cshtml";
}

<div class="col-md-8">
    <div>
        <h1 itemprop="name">CONTACT US</h1>
    </div>
    <hr />
   
    <h3>Send us a Message</h3>
    <br />
    @if (ViewBag.ContactUsSuccess != null)
    {
        <b style="color: green;">
            <p class="alert alert-success" style="text-align: center">@ViewBag.ContactUsSuccess</p>
        </b>
    }
    @if (ViewBag.ContactUsFailed != null)
    {
        <b style="color: red;">
            <p class="alert" style="text-align: center">@ViewBag.ContactUsFailed </p>
        </b>
    }
    @using (Html.BeginForm("ContactUs", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
    {
        <div class="control-group form-group">
            <div class="controls">
                @Html.LabelFor(m => m.QueryType)
                @Html.DropDownListFor(m => m.SelectValue, new SelectList(Model.QueryTypeList, "value", "text"), "Select Query Type", new { @class = "form-control" })
                @Html.ValidationMessageFor(m => m.SelectValue, "", new { @style = "color:red" })
            </div>
        </div>
        <div class="control-group form-group">
            <div class="controls">
                @Html.LabelFor(m => m.Name)
                @Html.TextBoxFor(m => m.Name, new { @class = "form-control" })
                @Html.ValidationMessageFor(m => m.Name, "", new { @style = "color:red" })
            </div>
        </div>
        <div class="control-group form-group">
            <div class="controls">
                @Html.LabelFor(m => m.EmailId)
                @Html.TextBoxFor(m => m.EmailId, new { @class = "form-control" })
                @Html.ValidationMessageFor(m => m.EmailId, "", new { @class = "", @style = "color:red" })
            </div>
        </div>
        <div class="control-group form-group">
            <div class="controls">
                @Html.LabelFor(m => m.ContactNumber)
                @Html.TextBoxFor(m => m.ContactNumber, new { @class = "form-control" })
            </div>
        </div>          
        <div class="control-group form-group">
            <div class="controls">
                @Html.LabelFor(m => m.QueryContent)
                @Html.TextAreaFor(m => m.QueryContent, new { @class = "form-control", rows = "3" })            
                @Html.ValidationMessageFor(m => m.QueryContent, "", new { @class = "", @style = "color:red" })
            </div>
        </div>
        <input type="submit" value="Send Message" id="btnSubmitQuery" class="btn btn-primary" />
           
    }

</div>

 

Use HTTP Verbs

Always use HTTP verbs which suitable to action method as HttpPut or HttpGet. If you don't put it will work as HttpGet by default.

But when adding something in database using insert operation, need to use HttpPut.

[HttpPost]
public ActionResult AddNewPost(MyViewModel model, string hdnTagList)
        

 

Use Bundling and Minification

As per Asp.Net MVC application performance we should always use Bundling and Minification. Using Bundling and Minification, we can make fewer request on server and decrease the file size which will download faster. Minification is achieved to use .min file. We can do Bundiling in BundleConfig class as following.

public class BundleConfig
{
        // For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862
        public static void RegisterBundles(BundleCollection bundles)
        {
            bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                        "~/Scripts/jquery-{version}.js"));

            // Use the development version of Modernizr to develop with and learn from. Then, when you're
            // ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
            bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
                        "~/Scripts/modernizr-*"));

            bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
                      "~/Scripts/bootstrap.js",
                      "~/Scripts/respond.js"));

            bundles.Add(new StyleBundle("~/Content/css").Include(
                      "~/Content/bootstrap.css",
                      "~/Content/site.css"));
        }
}

 

Use Area

If we are interested to create pluggable application in Asp.Net MVC then Area is the best option. Area provides separation of components. Using Area we can create multiple modules in same application where every module is working individually without affected to other functionality.

Mostly Area is used to create Backend module like Admin part in application. With following image, we can see that we have created three areas like Blog, InterviewAdmin, TutorialAdmin. Every Area component [blog] will contain own Controller folder, View folder and Models folder.

Area

 

Use Request Validation

Always use Request Validation as false [ValidateInput(false)]. By default it is true and this can causes security issue because if it is true then using html control we can pass html content to server. So, best practice to use Request Validation as false.

Enabling request validation in view pages would cause validation to occur after the input has already been processed by the controller. By default MVC performs request validation before a controller processes the input. To change this behavior applies the ValidateInputAttribute to a controller or action.

 

[ValidateInput(false)]
[OutputCache(CacheProfile = "MyCache")]
public ActionResult Index(string url)

 

Use Validation through DataAnnotation

Validation is the important part when working with any application. In Asp.Net MVC we can implement validation on server side using DataAnnotation which will found in using System.ComponentModel.DataAnnotations namespace.

After using this, we don't need to do extra workjust pass validation as per requirements like for checking the control is not empty use [Required] attribute, for max length validation just use [MaxLength] attribute with properties.

public class PostViewModel
{
       
        public int PostId { get; set; }

        [Display(Name="Post Title")]
        [Required(ErrorMessage="Post Title is required")]
        [RegularExpression(@"^.{5,}$", ErrorMessage = "Minimum 3 characters required")]
        [StringLength(500,MinimumLength=3, ErrorMessage="Invalid Title Lenght")]
        public string PostTitle { get; set; }


        [MaxLength(Int32.MaxValue, ErrorMessage = "More than max value")]
        [AllowHtml]        
        [Display(Name = "Short Content")]
        [Required(ErrorMessage = "Short Content is required")]        
        public string ShortPostContent { get; set; }

        [AllowHtml]
        [MaxLength(Int32.MaxValue, ErrorMessage = "More than max value")]
        [Display(Name = "Full Content")]
        [Required(ErrorMessage = "Full Content is required")]    
        public string FullPostContent { get; set; }

        [Display(Name = "Meta keywords")]
        [Required(ErrorMessage = "Meta Keywords is required")]    
        public string MetaKeywords { get; set; }

        [Display(Name = "Meta Description")]        
        public string MetaDescription { get; set; }
}

 

Use Only Single View Engine

In Asp.Net MVC, by default there are two engines available one is aspx engine and other one is razor engine. But it prefers to use only one engine for increasing performance of the application. So, first we need to clear ViewEngines when initializing the application and then bind our preferable engine with application.

ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new RazorViewEngine());

 

Conclusion:

So, today we have learned Best Practices when working with Asp.Net MVC application.

I hope this post will help you. Please put your feedback using comment which helps me to improve myself for next post. If you have any doubts please ask your doubts or query in the comment section and If you like this post, please share it with your friends. Thanks