.Net MVC C# OnActionExecuting example

A quick demo of how to hook up the OnActionExecuting method in an custom ActionFilter.

1) Create an ActionFilter class

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;

namespace CsharpWebAPIDemo.ActionFilters
{
    /// <summary>
    /// Custom action filter class for logging request variables
    /// </summary>
    public class LogActionFilter : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            LogRequestVars("OnActionExecuting", filterContext);
        }

        /// <summary>
        /// Logs the request vars.
        /// </summary>
        /// <param name="methodName">Name of the method.</param>
        /// <param name="values">The values.</param>
        private static void LogRequestVars(string methodName, ActionExecutingContext values)
        {
            // Get the request keys
            var keys = values.RequestContext.HttpContext.Request.Headers.AllKeys;

            // Get the request key value pairs
            var requestVars = keys.Select(key => new KeyValuePair<string, string>(key, values.RequestContext.HttpContext.Request.Headers.Get(key)));

            // Write to Debug log
            Debug.WriteLine("Method: {0}", methodName);

            foreach (var keyValuePair in requestVars)
            {
                Debug.WriteLine("{0} - {1}", keyValuePair.Key, keyValuePair.Value);
            }
        }
    }
}

2) Add the ActionFilter to you Controller class

using System.Web.Mvc;
using CsharpWebAPIDemo.ActionFilters;

namespace CsharpWebAPIDemo.Controllers
{
    public class HomeController : Controller
    {
        [LogActionFilter]
        public ActionResult Index()
        {
            return View();
        }
    }
}

The output is displayed in the output window of the debugger in Visual Studio.

.Net MVC C# simplest form post example

A quick post on Razor form posting, this is a really simple example – I’d avoid ViewBag if at all possible.

Add a form helper to your (Razor) view:

  @using (Html.BeginForm("Index", "Home", new { id = 1 }, FormMethod.Post))
    {
            @Html.TextBox("Input","Your value here")
            <input type="submit" class="submit" value="Sign Up" />
    }

Add a new method to your (Home) controller:

  // Accept HTTP POST method
  [HttpPost]
  public ActionResult Index(FormCollection collection)
  {
     // Avoid Viewbag, but fine for simple demo.
    ViewBag.postedValue = collection.Get(0);

    return View("~/views/Home/Results.cshtml");
  }

Add a new view to handle the post results:

@{
    ViewBag.Title = "Results";   
}

<h2>Results</h2>

@ViewBag.postedValue

C# .Net using Autofac in an MVC4 project

Autofac is a popular IoC container, it’s a little more complex to setup than some other containers available. I’ll describe how to do a simple setup to get up and running quickly.

If you’re new to IoC, it’s simply a mechanism for managing dependencies in your application, it’s now a hot topic in application development so it’s worth doing some research to familiarize yourself with the subject.

1) Create a new MVC4 solution in Visual Studio (2012 in this example).

2) Add the Autofac.MVC4 reference to your project, if you’re using nuget from the command line do:

install-package Autofac.MVC4

3) Add a new class AutofacScopeContainer.cs to your solution:

using System;
using System.Collections.Generic;
using  System.Web.Http.Dependencies;
using Autofac;
using Autofac.Integration.Mvc;

namespace CsharpAutofacDemo
{
    /// <summary>
    /// Autofac Scope Container
    /// </summary>
    public class AutofacScopeContainer : IDependencyScope
    {
        /// <summary>
        /// Private _container field
        /// </summary>
        private readonly AutofacDependencyResolver _container;

        /// <summary>
        /// Initializes a new instance of the <see cref="AutofacScopeContainer"/> class.
        /// </summary>
        /// <param name="container">The container.</param>
        /// <exception cref="System.ArgumentNullException">container</exception>
        protected AutofacScopeContainer(AutofacDependencyResolver container)
        {
            if (container == null)
            {
                throw new ArgumentNullException("container");
            }
            _container = container;
        }

        /// <summary>
        /// Retrieves a service from the scope.
        /// </summary>
        /// <param name="serviceType">The service to be retrieved.</param>
        /// <returns>
        /// The retrieved service.
        /// </returns>
        public object GetService(Type serviceType)
        {
            return _container.ApplicationContainer.IsRegistered(serviceType) ? _container.GetService(serviceType) : null;
        }

        /// <summary>
        /// Retrieves a collection of services from the scope.
        /// </summary>
        /// <param name="serviceType">The collection of services to be retrieved.</param>
        /// <returns>
        /// The retrieved collection of services.
        /// </returns>
        public IEnumerable<object> GetServices(Type serviceType)
        {
            return _container.ApplicationContainer.IsRegistered(serviceType) ? _container.GetServices(serviceType) : new List<object>();
        }

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            _container.ApplicationContainer.Dispose();
        }

    }

    /// <summary>
    /// Auto FacContainer
    /// </summary>
    public class AutoFacContainer : AutofacScopeContainer, IDependencyResolver
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="AutoFacContainer"/> class.
        /// </summary>
        /// <param name="container">The container.</param>
        public AutoFacContainer(AutofacDependencyResolver container)
            : base(container)
        {
        }

        /// <summary>
        /// Starts a resolution scope.
        /// </summary>
        /// <returns>
        /// The dependency scope.
        /// </returns>
        public IDependencyScope BeginScope()
        {
            return this;
        }
    }
}

4) Add a new class CustomerModel.cs to your solution:

namespace CsharpAutofacDemo.Models
{
    /// <summary>
    /// Customer class 
    /// </summary>
    public class Customer
    {
        public string CustomerId { get; set; }
        public string CustomerName { get; set; }
        public string CustomerAddress { get; set; }
        public string CustomerPhoneNumber { get; set; }
        public string CustomerEmail { get; set; }
    }
}

5) Add a new class CustomerRepository.cs to your solution:

using System.Collections.Generic;
using CsharpAutofacDemo.Models;

namespace CsharpAutofacDemo
{
    /// <summary>
    /// Customer details repository class
    /// </summary>
    public class CustomerRepository : ICustomerRepository
    {
        /// <summary>
        /// Get customer details.
        /// </summary>
        /// <returns></returns>
        public List<Customer> GetCustomerDetails()
        {
            // This is a simple implementation, others could use an ORM or Web service etc.
            
            var customers = new List<Customer>
                          {
                              new Customer()
                                  {
                                      CustomerId = "1",
                                      CustomerName = "Customer one",
                                      CustomerAddress = "Bristol",
                                      CustomerPhoneNumber = "0845000000",
                                      CustomerEmail = "[email protected]",
                                  },
                              new Customer()
                                  {
                                      CustomerId = "2",
                                      CustomerName = "Customer two",
                                      CustomerAddress = "Bath",
                                      CustomerPhoneNumber = "0845000001",
                                      CustomerEmail = "[email protected]",
                                  },
                              new Customer()
                                  {
                                      CustomerId = "3",
                                      CustomerName = "Customer three",
                                      CustomerAddress = "Swindon",
                                      CustomerPhoneNumber = "0845000003",
                                      CustomerEmail = "[email protected]",
                                  }
                          };

            return customers;
        }
    }
}

6) Add a new class ICustomerRepository.cs to your solution:

using System.Collections.Generic;
using CsharpAutofacDemo.Models;

namespace CsharpAutofacDemo
{
    /// <summary>
    /// ICustomerRepository interface
    /// </summary>
    public interface ICustomerRepository
    {
        List<Customer> GetCustomerDetails();
    }
}

7) Update your Global.asax.cs file:

using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using Autofac;
using Autofac.Integration.Mvc;
using System.Web;

namespace CsharpAutofacDemo
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : HttpApplication
    {
        protected void Application_Start()
        {
            RegisterAutoFac(GlobalConfiguration.Configuration);

            AreaRegistration.RegisterAllAreas();
            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();
        }

        void RegisterAutoFac(HttpConfiguration config)
        {
            // Setup the Container Builder
            var builder = new ContainerBuilder();

            // Register the controller in scope 
            builder.RegisterControllers(typeof(MvcApplication).Assembly);

            // Register types
            builder.RegisterType<CustomerRepository>().As<ICustomerRepository>();

            // Build the container
            var container = builder.Build();

            // Setup the dependency resolver
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

            config.DependencyResolver = new AutoFacContainer(new AutofacDependencyResolver(container));
        }
    }
}

8) Update your HomeController.cs file:

using System.Web.Mvc;

namespace CsharpAutofacDemo.Controllers
{
    /// <summary>
    /// MVC Controller class
    /// </summary>
    public class HomeController : Controller
    {
        /// <summary>
        /// Private _container field
        /// </summary>
        private readonly ICustomerRepository _customerRepository;

        /// <summary>
        /// Initializes a new instance of the <see cref="HomeController"/> class.
        /// </summary>
        /// <param name="customerRepository">The customer repository.</param>
        public HomeController(ICustomerRepository customerRepository)
        {
            _customerRepository = customerRepository;
        }

        // GET: /Customer/

        /// <summary>
        /// Method for index action.
        /// </summary>
        /// <returns></returns>
        public ActionResult Index()
        {
            //@model AutofacDemo.Customer
            var customer = _customerRepository.GetCustomerDetails();

            // View Index.cshtml
            return View(customer);
        }


    }
}

9) Update your index.cs file:

@model  List<CsharpAutofacDemo.Models.Customer>

@{
    ViewBag.Title = "Index";
}
<h2>Index</h2>

@foreach (var customer in Model)
{
    <fieldset>
        <legend>Customer</legend>

        <div class="display-label">
            @Html.DisplayNameFor(model => customer.CustomerId)
        </div>
        <div class="display-field">
            @Html.DisplayFor(model => customer.CustomerId)
        </div>
        <div class="display-label">
            @Html.DisplayNameFor(model => customer.CustomerName)
        </div>
        <div class="display-field">
            @Html.DisplayFor(model => customer.CustomerName)
        </div>
        <div class="display-label">
            @Html.DisplayNameFor(model => customer.CustomerAddress)
        </div>
        <div class="display-field">
            @Html.DisplayFor(model => customer.CustomerAddress)
        </div>
        <div class="display-label">
            @Html.DisplayNameFor(model => customer.CustomerPhoneNumber)
        </div>
        <div class="display-field">
            @Html.DisplayFor(model => customer.CustomerPhoneNumber)
        </div>

        <div class="display-label">
            @Html.DisplayNameFor(model => customer.CustomerEmail)
        </div>
        <div class="display-field">
            @Html.DisplayFor(model => customer.CustomerEmail)
        </div>
    </fieldset>
    <br />
}

10) Build your project and run, you should see the view page with the customer data displayed.

.Net MVC C# unit testing controllers

I’ve done some research in how to unit test MVC controllers effectively, the following pattern is a useful template for tests. Thanks to a great article from Jag Reehal

[Test]
public void ExampleTestOfAControllerMethod()
{
    // Arrange
    var testItem = ...;
    var testObject = Mock<IYourInterfaceToOject>();
    var yourController = new yourController(testObject.Object);
 
    // Act
    yourController.yourMethod(testItem);
 
    // Assert
    testObject.Verify(x => x.yourMethodUnderTest(testItem))
}

.Net MVC C# render nested HTML elements using a TagBuilder

The following HTMLHelper uses the TagBuilder class to render nested HTML elements.

public static class HtmlHelpers
    {
        public static MvcHtmlString RenderATag(this HtmlHelper htmlHelper, string uri, string cssClassName, string dataValue)
        {
            // Build A tag
            var aTagBuilder = new TagBuilder("a");

            aTagBuilder.MergeAttribute("href", uri);

            // Build I tag
            var iTagBuilder = new TagBuilder("i");

            // Add extension
            iTagBuilder.MergeAttribute("class", cssClassName);

            // Add the data attribute
            iTagBuilder.MergeAttribute("data-name", dataValue);

            // Render the end tag
            iTagBuilder.ToString(TagRenderMode.EndTag);

            // Add the I tag to the A tag
            aTagBuilder.InnerHtml += iTagBuilder.ToString();

            return new MvcHtmlString(aTagBuilder.ToString());
        }
    }

A simple ASP.Net MVC HTML Helper to truncate a string at an arbitrary length

public static MvcHtmlString DisplayNewsSearchSummary(this HtmlHelper htmlHelper, string input, int requiredLength, string ending = "...")
{
    // Validate and sanity check first...

   var requiredtext = input.Substring(0, requiredLength - 1);

   var ouputtext = string.Concat(requiredtext.Substring(0, requiredtext.LastIndexOf(' ')), ending);

   return new MvcHtmlString(descriptionText);
}