Validating a view model after custom model binding

Adapted from here:
https://stackoverflow.com/questions/13684354/validating-a-view-model-after-custom-model-binding

Usage:

CustomModelBinderHelper.DoValidation(bindingContext, indexViewModel);

Implementation:

    public static class CustomModelBinderHelper
    {
        /// <summary>
        /// https://stackoverflow.com/a/22652195/249895
        /// </summary>
        /// <param name="bindingContext"></param>
        /// <param name="model"></param>
        public static void DoValidation(ModelBindingContext bindingContext, IValidatableObject model)
        {
            var validationResults = new HashSet<ValidationResult>();
            var isValid = Validator.TryValidateObject(model, new ValidationContext(model, null, null), validationResults, true);
            if (!isValid)
            {
                var resultsGroupedByMembers = validationResults
                    .SelectMany(_ => _.MemberNames.Select(
                         x => new
                         {
                             MemberName = x ?? "",
                             Error = _.ErrorMessage
                         }))
                    .GroupBy(_ => _.MemberName);

                foreach (var member in resultsGroupedByMembers)
                {
                    bindingContext.ModelState.AddModelError(
                        member.Key,
                        string.Join(". ", member.Select(_ => _.Error)));
                }
            }
        }
    }

 

To be noted that objects have to implment System.ComponentModel.DataAnnotations.IValidatableObject interface.

Kendo Mvc CustomKendoMvcExtensions. DataSourceRequest Filters in case of Datetime comparison. Don’t take time into consideration

Usage:

return Json(requestsList.ToCustomDataSourceResult(request));

Or:

public ActionResult GetList([CustomDataSourceRequest]DataSourceRequest request)

Implementation:

using Kendo.Mvc;
using Kendo.Mvc.Extensions;
using Kendo.Mvc.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Web.Mvc;




namespace Kendo.Mvc.Extensions
{
    public static class CustomKendoMvcExtensions
    {
        /// <summary>
        /// Changes DataSourceRequest Filters in case of Datetime comparison. Does not take time into consideration
        /// //http://www.crowbarsolutions.com/ignoring-time-when-filtering-dates-in-telerik-kendo-grids/
        /// Adapted from above link.
        /// Uses CustomDataSourceRequestModelBinder.TransformFilterDescriptors function
        /// </summary>
        /// <param name="queryable"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        public static DataSourceResult ToCustomDataSourceResult(this IQueryable queryable, DataSourceRequest request)
        {
            if (request.Filters != null && request.Filters.Count > 0)
            {

                ModelBinders.CustomDataSourceRequestModelBinder customModelBinder = new ModelBinders.CustomDataSourceRequestModelBinder();

                var transformedFilters = request.Filters.Select(customModelBinder.TransformFilterDescriptors).ToList();
                request.Filters = transformedFilters;
            }

            return queryable.ToDataSourceResult(request);
        }
    }
}


namespace Kendo.Mvc.UI
{
    //http://www.crowbarsolutions.com/ignoring-time-when-filtering-dates-in-telerik-kendo-grids/
    public class CustomDataSourceRequestAttribute : DataSourceRequestAttribute
    {
        public override IModelBinder GetBinder()
        {
            return new Kendo.Mvc.ModelBinders.CustomDataSourceRequestModelBinder();
        }
    }
}

namespace Kendo.Mvc.ModelBinders
{
    /// <summary>
    /// DateTime filtering is horribly unintuitive in Kendo Grids when a non-default (00:00:00) time is attached
    /// to the grid's datetime data. We use this custom model binder to transform the grid filters to return 
    /// results that ignore the attached time, leading to intuitive results that make users happy.
    /// 
    /// To use the code, substitute the [DataSourceRequest] attribute for [CustomDataSourceRequest] in your MVC controller
    /// </summary>
    public class CustomDataSourceRequestModelBinder : IModelBinder
    {
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            // Get an instance of the original kendo model binder and call the binding method
            var baseBinder = new DataSourceRequestModelBinder();
            var request = (DataSourceRequest)baseBinder.BindModel(controllerContext, bindingContext);

            if (request.Filters != null && request.Filters.Count > 0)
            {
                var transformedFilters = request.Filters.Select(TransformFilterDescriptors).ToList();
                request.Filters = transformedFilters;
            }

            return request;
        }

        public IFilterDescriptor TransformFilterDescriptors(IFilterDescriptor filter)
        {
            if (filter is CompositeFilterDescriptor)
            {
                var compositeFilterDescriptor = filter as CompositeFilterDescriptor;
                var transformedCompositeFilterDescriptor = new CompositeFilterDescriptor { LogicalOperator = compositeFilterDescriptor.LogicalOperator };
                foreach (var filterDescriptor in compositeFilterDescriptor.FilterDescriptors)
                {
                    transformedCompositeFilterDescriptor.FilterDescriptors.Add(TransformFilterDescriptors(filterDescriptor));
                }
                return transformedCompositeFilterDescriptor;
            }
            if (filter is FilterDescriptor)
            {
                var filterDescriptor = filter as FilterDescriptor;
                if (filterDescriptor.Value is DateTime)
                {
                    var value = (DateTime)filterDescriptor.Value;
                    switch (filterDescriptor.Operator)
                    {
                        case FilterOperator.IsEqualTo:
                            //convert the "is equal to <date><time>" filter to a "is greater than or equal to <date> 00:00:00" AND "is less than or equal to <date> 23:59:59"
                            var isEqualCompositeFilterDescriptor = new CompositeFilterDescriptor { LogicalOperator = FilterCompositionLogicalOperator.And };
                            isEqualCompositeFilterDescriptor.FilterDescriptors.Add(new FilterDescriptor(filterDescriptor.Member,
                                FilterOperator.IsGreaterThanOrEqualTo, new DateTime(value.Year, value.Month, value.Day, 0, 0, 0)));
                            isEqualCompositeFilterDescriptor.FilterDescriptors.Add(new FilterDescriptor(filterDescriptor.Member,
                                FilterOperator.IsLessThanOrEqualTo, new DateTime(value.Year, value.Month, value.Day, 23, 59, 59)));
                            return isEqualCompositeFilterDescriptor;

                        case FilterOperator.IsNotEqualTo:
                            //convert the "is not equal to <date><time>" filter to a "is less than <date> 00:00:00" OR "is greater than <date> 23:59:59"
                            var notEqualCompositeFilterDescriptor = new CompositeFilterDescriptor { LogicalOperator = FilterCompositionLogicalOperator.Or };
                            notEqualCompositeFilterDescriptor.FilterDescriptors.Add(new FilterDescriptor(filterDescriptor.Member,
                                FilterOperator.IsLessThan, new DateTime(value.Year, value.Month, value.Day, 0, 0, 0)));
                            notEqualCompositeFilterDescriptor.FilterDescriptors.Add(new FilterDescriptor(filterDescriptor.Member,
                                FilterOperator.IsGreaterThan, new DateTime(value.Year, value.Month, value.Day, 23, 59, 59)));
                            return notEqualCompositeFilterDescriptor;

                        case FilterOperator.IsGreaterThanOrEqualTo:
                            //convert the "is greater than or equal to <date><time>" filter to a "is greater than or equal to <date> 00:00:00"
                            filterDescriptor.Value = new DateTime(value.Year, value.Month, value.Day, 0, 0, 0);
                            return filterDescriptor;

                        case FilterOperator.IsGreaterThan:
                            //convert the "is greater than <date><time>" filter to a "is greater than <date> 23:59:59"
                            filterDescriptor.Value = new DateTime(value.Year, value.Month, value.Day, 23, 59, 59);
                            return filterDescriptor;

                        case FilterOperator.IsLessThanOrEqualTo:
                            //convert the "is less than or equal to <date><time>" filter to a "is less than or equal to <date> 23:59:59"
                            filterDescriptor.Value = new DateTime(value.Year, value.Month, value.Day, 23, 59, 59);
                            return filterDescriptor;

                        case FilterOperator.IsLessThan:
                            //convert the "is less than <date><time>" filter to a "is less than <date> 00:00:00"
                            filterDescriptor.Value = new DateTime(value.Year, value.Month, value.Day, 0, 0, 0);
                            return filterDescriptor;

                        default:
                            throw new Exception(string.Format("Filter operator '{0}' is not supported for DateTime member '{1}'", filterDescriptor.Operator, filterDescriptor.Member));
                    }
                }
            }
            return filter;
        }
    }
}

Left side, vertical, scroll through menu

If you want to create a vertical menu that scrolls through the items as you scrolls through the page

 

HTML:

<nav id="leftMenu">
	<ul class="sidebar-nav nav leftMenuItems padding-0">
		<li><h4>Navigation Menu</h4></li>
		<li class="active">     <a id="menuItem202" href="#formSectionInstance_202">Menu Item 1</a> </li>
		<li><a id="menuItem203" href="#formSectionInstance_203">Menu Item 2<</a></li>
		<li><a id="menuItem204" href="#formSectionInstance_204">Menu Item 3<</a></li>
		<li><a id="menuItem208" href="#formSectionInstance_208">Menu Item 4<</a></li>
		<li><a id="menuItem206" href="#formSectionInstance_206">Menu Item 5<</a></li>
		<li><a id="menuItem207" href="#formSectionInstance_207_documentUpload">Menu Item 6<</a></li>
	</ul>
</nav>

 

Javascript:

function BindEventsToFormMenuItems()
{
	// Cache selectors
	var lastId,
		topMenu = $("#navbar"),
		leftMenu = $("#leftMenu"),
		topMenuHeight = topMenu.outerHeight() + 15,
		// All list items
		menuItems = leftMenu.find("a"),
		// Anchors corresponding to menu items
		scrollItems = menuItems.map(function ()
		{
			var item = $($(this).attr("href"));
			if (item.length) { return item; }
		});

	// Bind click handler to menu items
	// so we can get a fancy scroll animation
	menuItems.each(function (index) {
		$(this).click(function (e) {
			var href = $(this).attr("href"),
				offsetTop = href === "#" ? 0 : $(href).offset().top - topMenuHeight + 1;
			$('html, body').stop().animate({
				scrollTop: offsetTop
			}, 300);
			e.preventDefault();
			
			if ($('#menu-toggle').is(':visible'))
			{
				$("#menu-toggle").trigger("click");
			}

			menuItems.parent().removeClass("active");
			$(this).parent().addClass("active");
		});
	});

	// Bind to scroll
	$(window).scroll(function ()
	{
		// Get container scroll position
		var fromTop = $(this).scrollTop() + topMenuHeight + 50;

		// Get id of current scroll item
		var cur = scrollItems.map(function ()
		{
			if ($(this).offset().top < fromTop)
				return this;
		});
		// Get the id of the current element
		cur = cur[cur.length - 1];
		var id = cur && cur.length ? cur[0].id : "";

		if (lastId !== id)
		{
			lastId = id;
			// Set/remove active class
			menuItems
			  .parent().removeClass("active")
			  .end().filter("[href='#" + id + "']").parent().addClass("active");
		}
	});
}

Web.config transform from template and transformation files

This solution is usefull when you want to debug on multiple environments.

Just add ad template file, some transformation config files and then select your desired Solution configuration.

Web config will be changed on the spot.

 

Also usefull when you want to publish on different environments.

 

You can setup different web.cofig configurations.

<Target Name="BeforeBuild">
    <TransformXml Source="$(WebFolderName)Web.Template.config" Transform="$(WebFolderName)Web.$(Configuration).config" Destination="$(WebFolderName)Web.config" />
</Target>

Kendo Mvc GridHelper

Code beautifier: http://hilite.me/

Usage

@(Html.CustomKendoGrid<ViewModels.UserViewModel>("grid"))

Code:

namespace Kendo.Mvc.UI
{
    //read here about Func vs Action https://stackoverflow.com/a/12687775/249895
    public static class KendoMvcGridHelper
    {

        public static readonly int AxajPageSize = 20;
        public static readonly int AxajPageSizeSmall = 10;

        public static Kendo.Mvc.UI.Fluent.GridBuilder CustomKendoGrid(this HtmlHelper helper, string name) where T : class
        {
            var returnGridBuilder = helper.Kendo().Grid();
            returnGridBuilder = returnGridBuilder.Name(name);
            returnGridBuilder = ConfigureGridBuilder(returnGridBuilder);

            return returnGridBuilder;
        }

        private static GridBuilder ConfigureGridBuilder(GridBuilder gridBuilder) where T : class
        {
            gridBuilder = gridBuilder.Pageable(p => p.PageSizes(new List<int>() { 10, 20 }));
            gridBuilder = gridBuilder.Sortable();
            gridBuilder = gridBuilder.Resizable(r => r.Columns(true));
            gridBuilder = gridBuilder.Filterable(ConfigureGridFilterableSettingsBuilder);
            gridBuilder = gridBuilder.Pageable();
            return gridBuilder;
        }


        public static void ConfigureGridFilterableSettingsBuilder(GridFilterableSettingsBuilder config)        
        {
            config = config.Mode(GridFilterMode.Row).Extra(false);
            config = config.Operators(ConfigureFilterableOperators);
        }

        public static void ConfigureFilterableOperators(FilterableOperatorsBuilder operators)
        {
            operators = operators.ForString(str => str.Clear()
                        .IsEqualTo("Is equal to")
                        .IsNotEqualTo("Is not equal to")
                        .StartsWith("Starts with")
                        .EndsWith("Ends with")                        
                        .Contains("Contains")
                        .DoesNotContain("Does not contain")
                    )
                    .ForDate(str => str.Clear()
                        .IsEqualTo("Is Equal To")
                        .IsGreaterThan("Is Greater Than")
                        .IsGreaterThanOrEqualTo("Is Greater Than Or Equal To")
                        .IsLessThan("Is Less Than")
                        .IsLessThanOrEqualTo("Is Less Than Or Equal To")
                        .IsNotEqualTo("Is Not Equal To")
                    )
                    .ForEnums(str => str.Clear()
                        .IsEqualTo("Is Equal To")
                        .IsNotEqualTo("Is Not Equal To")
                    )
                    .ForNumber(str => str.Clear()
                        .IsEqualTo("Is Equal To")
                        .IsGreaterThan("Is Greater Than")
                        .IsGreaterThanOrEqualTo("Is Greater Than Or Equal To")
                        .IsLessThan("Is Less Than")
                        .IsLessThanOrEqualTo("Is Less Than Or Equal To")
                        .IsNotEqualTo("Is Not Equal To")
                    );
        }
    }
}

MVC CustomAuthorizeAttribute using Reflection to get Controllers and Actions

Code beautifier used: http://hilite.me/ 

Usage:

    [CustomAuthorize]
    public class AdministrationController : BaseController
    {
        #region Users List

        [NavigationMenuEnumAuthorize(NavigationMenuEnum.UserAdministration)]
        public ActionResult Index()
        {
            return View();
        }
    }

CustomAuthorizeAttrbute Code:

namespace System.ComponentModel.DataAnnotations
{

    public class NavigationMenuEnumAuthorizeAttribute : System.Attribute
    {
        public List NavigationMenuEnumList { get; set; }
        public NavigationMenuEnumAuthorizeAttribute(params NavigationMenuEnum[] navigationPages)
        {
            NavigationMenuEnumList = new List();
            if (navigationPages != null && navigationPages.Count() > 0)
            {
                NavigationMenuEnumList = navigationPages.ToList();
            }
        }
    }

    public class CustomAuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
    {
        string currentAction;
        string currentController;
        string currentArea;
        public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext)
        {
            base.OnAuthorization(filterContext);
        }

        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            var routeData = httpContext.Request.RequestContext.RouteData;

            currentAction = routeData.GetRequiredString("action");
            currentController = routeData.GetRequiredString("controller");
            currentArea = routeData.Values["area"] as string;

            if (Utils.CurrentUser == null)
                return false;

            Dictionary<NavigationMenuEnum, bool> menuSecurity = new Dictionary<NavigationMenuEnum, bool>();

            using (var dbContext = new Web.Models.ConnectionStringEDMX())
            {
                int userid = Utils.CurrentUser.UserId;

                menuSecurity[NavigationMenuEnum.CreateNewForm] = false;
                menuSecurity[NavigationMenuEnum.CreateNewChildForm] = false;
                menuSecurity[NavigationMenuEnum.EditNewForm] = false;
                menuSecurity[NavigationMenuEnum.FormSummary] = false;
                menuSecurity[NavigationMenuEnum.AllRequests] = false;
                menuSecurity[NavigationMenuEnum.MyRequests] = false;
                menuSecurity[NavigationMenuEnum.WaitingForApproval] = false;
                menuSecurity[NavigationMenuEnum.UserAdministration] = false;
                menuSecurity[NavigationMenuEnum.Delegate] = false;
                menuSecurity[NavigationMenuEnum.Reporting] = false;

                if (userid == 0)
                {
                    httpContext.Session[Web.Helpers.StaticStrings.MenuSecuritySessionName] = (Dictionary<NavigationMenuEnum, bool>)menuSecurity;
                    return false;
                }

                var userRoles = dbContext.admUserRoles.Where(x => x.UserId == userid || Utils.CurrentUser.CurrentUserDelegatedForUserIdList.Contains(x.UserId));

                foreach (admUserRole userRole in userRoles)
                {
                    switch ((EnRoles)userRole.RoleId)
                    {
                        case EnRoles.Admin:
                            {
                                menuSecurity[NavigationMenuEnum.CreateNewForm] = true;
                                menuSecurity[NavigationMenuEnum.CreateNewChildForm] = true;
                                menuSecurity[NavigationMenuEnum.EditNewForm] = true;
                                menuSecurity[NavigationMenuEnum.AllRequests] = true;
                                menuSecurity[NavigationMenuEnum.MyRequests] = true;
                                menuSecurity[NavigationMenuEnum.WaitingForApproval] = true;
                                menuSecurity[NavigationMenuEnum.FormSummary] = true;
                                menuSecurity[NavigationMenuEnum.UserAdministration] = true;
                                menuSecurity[NavigationMenuEnum.Delegate] = true;
                                menuSecurity[NavigationMenuEnum.Reporting] = true;
                                break;
                            }
                        case EnRoles.Originator:
                            {
                                menuSecurity[NavigationMenuEnum.CreateNewForm] = true;
                                menuSecurity[NavigationMenuEnum.CreateNewChildForm] = true;
                                menuSecurity[NavigationMenuEnum.EditNewForm] = true;
                                menuSecurity[NavigationMenuEnum.FormSummary] = true;
                                menuSecurity[NavigationMenuEnum.AllRequests] = true;
                                menuSecurity[NavigationMenuEnum.MyRequests] = true;
                                menuSecurity[NavigationMenuEnum.Delegate] = true;
                                break;
                            }
                        case EnRoles.Reviewer:
                            {
                                menuSecurity[NavigationMenuEnum.AllRequests] = true;
                                menuSecurity[NavigationMenuEnum.WaitingForApproval] = true;
                                menuSecurity[NavigationMenuEnum.FormSummary] = true;
                                menuSecurity[NavigationMenuEnum.Delegate] = true;
                                break;
                            }
                        case EnRoles.Approver:
                            {
                                menuSecurity[NavigationMenuEnum.AllRequests] = true;
                                menuSecurity[NavigationMenuEnum.WaitingForApproval] = true;
                                menuSecurity[NavigationMenuEnum.FormSummary] = true;
                                menuSecurity[NavigationMenuEnum.Delegate] = true;
                                break;
                            }
                        case EnRoles.Reporting:
                            {
                                menuSecurity[NavigationMenuEnum.AllRequests] = true;
                                menuSecurity[NavigationMenuEnum.Reporting] = true;
                                menuSecurity[NavigationMenuEnum.Delegate] = true;
                                break;
                            }
                        case EnRoles.Viewer:
                            {
                                menuSecurity[NavigationMenuEnum.AllRequests] = true;
                                menuSecurity[NavigationMenuEnum.Delegate] = true;
                                menuSecurity[NavigationMenuEnum.FormSummary] = true;
                                break;
                            }
                        case EnRoles.Supervisor:
                            {
                                menuSecurity[NavigationMenuEnum.AllRequests] = true;
                                menuSecurity[NavigationMenuEnum.WaitingForApproval] = true;
                                menuSecurity[NavigationMenuEnum.FormSummary] = true;
                                menuSecurity[NavigationMenuEnum.Delegate] = true;
                                break;
                            }
                        default:
                            {
                                break;
                            }
                    }
                }
            }

            httpContext.Session[Web.Helpers.StaticStrings.MenuSecuritySessionName] = (Dictionary<NavigationMenuEnum, bool>)menuSecurity;
            
            List pageMapping = GetGeneralPageDetailsList(); // all page mappings are generating from controllers that have the CustomAuthorizeAttribute and Actions that have the NavigationMenuEnumAuthorizeAttribute


            if (!pageMapping.Any(x => x.Action == currentAction && x.Controller == currentController))
                return true;

            NavigationMenuEnum currentPage = pageMapping.Where(x => x.Action == currentAction && x.Controller == currentController).Select(x => x.Page).FirstOrDefault();

            return menuSecurity[currentPage];
        }

        public class PageDetails
        {
            public string Action { get; set; }
            public string Controller { get; set; }
            public NavigationMenuEnum Page { get; set; }
            public PageDetails(string action, string controller, NavigationMenuEnum page)
            {
                this.Action = action;
                this.Controller = controller;
                this.Page = page;
            }
                }

        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {            
            if (Utils.CurrentUser == null || Utils.CurrentUser.UserId == 0)
            {
                filterContext.Result = new RedirectToRouteResult(
                        new RouteValueDictionary 
                        {
                            { "area", "" },
                            { "controller", "Home" },
                            { "action", "SignIn" }
                        });
            }
            else
            {
                filterContext.Result = new RedirectToRouteResult(
                        new RouteValueDictionary 
                        {
                            { "area", "" },
                            { "controller", "Account" },
                            { "action", "NoAccess" }
                        });
            }
            return;
            base.HandleUnauthorizedRequest(filterContext);
        }

        /// https://stackoverflow.com/a/11305443/249895
        public List GetGeneralPageDetailsList()
        {
            try
            {
                ///https://stackoverflow.com/a/30969888/249895
                Assembly asm = Assembly.GetAssembly(typeof(MvcApplication));

                var controllerTypesList = asm.GetTypes().Where(type => typeof(System.Web.Mvc.Controller).IsAssignableFrom(type));

                var returnPagesList = new List();

                foreach (var controllerType in controllerTypesList)
                {
                    var reflectedControllerDescriptor = new ReflectedControllerDescriptor(controllerType);
                    string controllerName = reflectedControllerDescriptor.ControllerName;
                    var customAuthorizeAttributeList = reflectedControllerDescriptor.GetCustomAttributes(typeof(CustomAuthorizeAttribute), true);

                    if (customAuthorizeAttributeList != null && customAuthorizeAttributeList.Count() > 0)
                    {
                        var actionsList = reflectedControllerDescriptor.GetCanonicalActions();
                        foreach (var action in actionsList)
                        {
                            var attributesList = action.GetCustomAttributes(typeof(NavigationMenuEnumAuthorizeAttribute), true).Select(x => (NavigationMenuEnumAuthorizeAttribute)x).ToList();
                            if (attributesList != null && attributesList.Count() > 0)
                            {
                                foreach (var attribute in attributesList)
                                {
                                    foreach (var navigMenuEnum in attribute.NavigationMenuEnumList)
                                    {
                                        var page = new CustomAuthorizeAttribute.PageDetails(action.ActionName, controllerName, navigMenuEnum);
                                        returnPagesList.Add(page);
                                    }
                                }
                            }
                            else
                            {
                                var page = new CustomAuthorizeAttribute.PageDetails(action.ActionName, controllerName, NavigationMenuEnum.None);
                                returnPagesList.Add(page);
                            }
                        }
                    }
                }

                return returnPagesList;
            }
            catch (ReflectionTypeLoadException ex)
            {
                System.Text.StringBuilder sb = new System.Text.StringBuilder();
                foreach (Exception exSub in ex.LoaderExceptions)
                {
                    sb.AppendLine(exSub.Message);
                    System.IO.FileNotFoundException exFileNotFound = exSub as System.IO.FileNotFoundException;
                    if (exFileNotFound != null)
                    {
                        if (!string.IsNullOrEmpty(exFileNotFound.FusionLog))
                        {
                            sb.AppendLine("Fusion Log:");
                            sb.AppendLine(exFileNotFound.FusionLog);
                        }
                    }
                    sb.AppendLine();
                }
                string errorMessage = sb.ToString();
                Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
                Exception newEx = new Exception(errorMessage);
                Elmah.ErrorSignal.FromCurrentContext().Raise(newEx);
                throw newEx;
                //Display or log the error based on your application.
            }
            catch (Exception ex)
            {
                Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
                throw;
            }
        }
    }


}