Fransiscus Setiawan | EV Charging & Azure Solution Architect | Sydney

Technical Insights: Azure, .NET, Dynamics 365 & EV Charging Architecture

Build Custom View Engine to override default views folder in ASP.NET MVC

So here is the situation, I need to build a personalization for the user where they can have different View files based on their user preference or alternatively they can pick their own View folder. To better explain the situation, look at the folder structure below

ViewPersonalisation-FolderStructure

So basically, I don’t want it to be under “Views” folder anymore instead I want my views to be under “Media” folder and by default if the user hasn’t specified which “Views” folder that they want to select then it should use the default one which is “Main” folder

First of all, we need to create our own View Engine that inherits from “RazorViewEngine” and then we need to override the default “ViewLocation“, “PartialViewLocation” and “MasterLocation” with our own default location which is “Media”

Secondly, we need to override “CreateView” method and “CreatePartialView” method to replace the default view location with the one defined in database/user settings

*Note: in the code below “CacheManager.CurrentSite.FolderPath” is storing the “Views” folder that the user has selected in their profile. “UseCustomViewLocation” function is used in this case to not have the personalisation on any of the “Admin Area”
[code language=”csharp”]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.IO;</code>

namespace WebUI.Custom.ViewEngine
{
public class WhitelabelViewEngine : RazorViewEngine
{
private const string WHITELABELVIEWFOLDER = "Whitelabel";
private const string MAINFOLDER = "Main";
private const string EXCLUDED_AREA = "admin";

public WhitelabelViewEngine()
{
base.ViewLocationFormats = new[] {
"~/Media/" + MAINFOLDER + "/{1}/{0}.cshtml",
"~/Media/" + MAINFOLDER + "/{1}/{0}.vbhtml",
"~/Media/" + MAINFOLDER + "/Shared/{0}.cshtml",
"~/Media/" + MAINFOLDER + "/Shared/{0}.vbhtml"
};

base.MasterLocationFormats = new[] {
"~/Media/" + MAINFOLDER + "/{1}/{0}.cshtml",
"~/Media/" + MAINFOLDER + "/{1}/{0}.vbhtml",
"~/Media/" + MAINFOLDER + "/Shared/{0}.cshtml",
"~/Media/" + MAINFOLDER + "/Shared/{0}.vbhtml"
};

base.PartialViewLocationFormats = new[] {
"~/Media/" + MAINFOLDER + "/{1}/{0}.cshtml",
"~/Media/" + MAINFOLDER + "/{1}/{0}.vbhtml",
"~/Media/" + MAINFOLDER + "/Shared/{0}.cshtml",
"~/Media/" + MAINFOLDER + "/Shared/{0}.vbhtml"
};
}

protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
{
IView partialView = base.CreatePartialView(controllerContext, partialPath);

if (UseCustomViewLocation(controllerContext))
{
partialView = base.CreatePartialView(controllerContext, partialPath.Replace(MAINFOLDER, CacheManager.CurrentSite.FolderPath));

if (!File.Exists(controllerContext.HttpContext.Server.MapPath(((RazorView)partialView).ViewPath)))
partialView = base.CreatePartialView(controllerContext, partialPath);
}

return partialView;
}

protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
{
IView pageView = base.CreateView(controllerContext, viewPath, masterPath);

if (UseCustomViewLocation(controllerContext))
{
pageView = base.CreateView(controllerContext, viewPath.Replace(MAINFOLDER, CacheManager.CurrentSite.FolderPath),
masterPath.Replace(MAINFOLDER, CacheManager.CurrentSite.FolderPath));

if (!File.Exists(controllerContext.HttpContext.Server.MapPath(((RazorView)pageView).ViewPath)))
pageView = base.CreateView(controllerContext, viewPath, masterPath);
}

return pageView;
}

///
/// to check whether in the custom area or not
///

//////
private bool UseCustomViewLocation(ControllerContext controllerContext)
{
bool useCustomViewLocation = false;

if (controllerContext.RouteData.DataTokens["area"] == null || (controllerContext.RouteData.DataTokens["area"] != null &amp;&amp; controllerContext.RouteData.DataTokens["area"] != EXCLUDED_AREA))
{
useCustomViewLocation = true;
}

return useCustomViewLocation;
}
}
}
[/code]

Lastly, We also need to register our custom view engine in Global.asax
[code language=”csharp”]
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
BootStrapper.Setup();

/*Register Whitelabel View Engine logic*/
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new WhitelabelViewEngine());
}
}
[/code]
 

Custom Principal in ASP.NET

Great sample on how to implement Custom Principal in ASP.NET

http://www.creatingsoftware.net/2007/11/aspnet-20-forms-authentication-keeping.html

I’ll be using this technique to integrate with ASP.NET MVC so I can avoid using Session State completely

Excellent article about System.Collections in .NET

http://geekswithblogs.net/BlackRabbitCoder/archive/2011/06/16/c.net-fundamentals-choosing-the-right-collection-class.aspx

Entity Framework – Schema MigrateDatabaseToLatestVersion

I’ve been using EF for quite sometimes and I use Code First to build my schema. The question that I always have in mind is “Once the project is released and we need to add a new entity or add a new column  to the existing entity, how do we tackle that?” and the question is even asked by my colleague. My answer was “oh, we can track down our changes by hand on a SQL file” and “I also try to be smart by saying we can get the latest production DB and compare it with the Development DB locally by using Database project or by using RedGate Schema Compare”

 

I’m still not happy even with my own answer!! and I believe that it’s not only me facing this problem and Microsoft should be smart enough to tackle this problem. So I start doing my research and I found the answer that I’m looking for – EF has an initializer called “MigrateDatabaseToLatestVersion” which accept 2 parameters DB Context and Configuration. So what is Configuration?It is a class that inherits from DbMigrationsConfiguration

So how do I get this class?There are 2 possible ways:

1. Use PackageManager Console (on your data layer project) and type the code below and it will create a new folder called “Migration” and a file with name “Configuration”

[code language=”bash”]PM>enable-migrations -enableautomaticmigration [/code]

2. Create a file called “Configuration.cs/.vb” or with whatever name that you wanted and paste the code below

[code language=”csharp”]
namespace GenericSolution.Data.Migrations
{
using System;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq;
using GenericSolution.Data;

internal sealed class Configuration : DbMigrationsConfiguration<GenericSolutionContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
//***DO NOT REMOVE THIS LINE,
//DATA WILL BE LOST ON A BREAKING SCHEMA CHANGE,
//TALK TO OTHER PARTIES INVOLVED IF THIS LINE IS CAUSING PROBLEMS
AutomaticMigrationDataLossAllowed = true;
}

protected override void Seed(GenericSolutionContext context)
{
// This method will be called after migrating to the latest version.

// You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = "Andrew Peters" },
// new Person { FullName = "Brice Lambson" },
// new Person { FullName = "Rowan Miller" }
// );
//
}
}
}
[/code]

*AutomaticMigrationDataLossAllowed is a property that allow you to automatically drop the column from the schema when you remove a property from your entity class. By default, it sets to false which means it will throw an exception “AutomaticDataLossException” when you try to remove column from your table. So please use it cautiously

Next step is to use this configuration on your DBContext initializer which can be on your DBFactory class

[code language=”csharp”]
public DBFactory()
{
//Create database when not exists with code below
//Database.SetInitializer(new CreateDatabaseIfNotExists<GenericSolutionContext>());

//Pass null when you already have the database exists and no changes
//Database.SetInitializer<GenericSolutionContext>(null);

//Automatic schema migration
Database.SetInitializer(new MigrateDatabaseToLatestVersion<GenericSolutionContext, Configuration>());

}
[/code]

There is another class that will create an empty migration so that the future migrations will start from the current state of your database. I will update this blog once I know in detail about the functionality of it

1. Getting it by using PM Console

[code language=”bash”]PM> Add-Migration InitialMigration -IgnoreChanges[/code]

2. Create a class

[code language=”csharp”]
namespace GenericSolution.Data.Migrations
{
using System;
using System.Data.Entity.Migrations;

public partial class InitialMigration : DbMigration
{
public override void Up()
{
}

public override void Down()
{
}
}
}
[/code]

Run a selective column query in Entity Framework

EF is an ORM tool for Microsoft. It helps developer in interacting with the database (CRUD) and running a custom stored procedure. I’ve been using it and it’s all running perfectly fine. But I have a problem with querying an entity, when I try to query an entity by default it will run a SELECT * or selecting all columns, but for some data intensive application I might just require 2 columns instead of all columns. I’m not too concerned with a simple table with a few columns but how about when you have a or more than one BLOB/Varbinary/NVARCHAR(MAX) and you need 100 or 1000 rows records with a 2 single columns or even just an ID column. By default it will return all the columns but then you can use PROJECTION

[code language=”csharp”]
var q = from r in Context.TableName
select new
{
Id = r.Id,
Status = r.Status
}
[/code]

Let’s take it to another level, I’m building a common library for all entities and can be used dynamically by passing the column to the function

[code language=”csharp”]
/// <summary>
/// Dynamic Select query that loads only specific column passed in parameter and also based on the where clause that passed as a parameter
/// </summary>
/// <typeparam name="U"></typeparam>
/// <param name="columns"></param>
/// <param name="where"></param>
/// <returns></returns>
public IEnumerable<U> GetBy<U>(Expression<Func<T, U>> columns, Expression<Func<T, bool>> where)
{
return dbset.Where(where).Select<T,U>(columns);
}
[/code]

And it can be called as below and it will return me an IEnumerable of Anonymous object which then I need to process it manually to map with the actual entity

[code language=”csharp”]
_userRepository.GetBy(u => new { u.UserName, u.FirstName }, f => f.UserName == UserName)
[/code]

So the question is now how do I modify this function to return me the actual entity or else make a single function that just work across all entities without requiring manual mapping.
We can use Automapper – (you can get this from NuGet) to map your Anonymous Object with your base Entity function, so this combines the Generic <T> of entity with the projection as the parameter to select
a few specific columns) and it will return back the collection of the entity that you requested

[code language=”csharp”]
/// <summary>
/// Dynamic Select query that loads only specific column passed in parameter and also based on the where clause that passed as a parameter
/// </summary>
/// <typeparam name="U"></typeparam>
/// <param name="columns"></param>
/// <param name="where"></param>
/// <returns></returns>
public IEnumerable<T> GetBy<U>(Expression<Func<T, U>> columns, Expression<Func<T, bool>> where)
{
//Create an initial mapping between anonymous object and returned entity type
Mapper.CreateMap<U, T>();
var anonymousList = dbset.Where(where).Select<T, U>(columns);
return Mapper.Map<IEnumerable<U>, IEnumerable<T>>(anonymousList);
}
[/code]

Enum in javascript and binding it to Dropdown list

It’s pretty clean to set, bind and use enum in your javascript

//Enum declaration
var AvailableActions = { “Action”: 1, “Priority”: 2, “Status”: 3 };

//Bind
function Load()
{
for (var action in AvailableActions) {
jQuery(“#MandatoryActionList”).append(“<option value=” + AvailableActions[action] + “>” + action + “</option>”);
}
}

//Use the enum
AvailableActions[“Priority”] will return 2
action will return the string representation in this case e.g “Action”, “Priority”, or “Status”

SQL Splitting function performance

I was required to create a SQL Splitter function and I tried to browse internet to find an article about it but I never thought there is someone has done wonderful job in comparing the performance of his SQL Split function including with the benchmark and technical break down. Now based on this article, I’m quite sure I have a strong/high performance SQL Splitter function

http://bradsruminations.blogspot.com.au/2010/08/integer-list-splitting-sql-fable.html

Regards,
Fransiscus

Best practice of creating a custom exception in .NET

This is a great article explaining how to create a custom exception that follows the standard

http://dotnetconcepts.wordpress.com/2010/05/28/custom-exceptions-in-c/

Degrading performance IIS 7 with Windows Authentication and Kerberos

If you use IIS7 with windows authentication and kerberos, you might want to look into this support article from microsoft. This support article also cover IIS6

http://support.microsoft.com/kb/954873

IIF in SQL Server 2012

Now you can use IIF in SQL Server 2012 instead of CASE (again this only if you have 2 possible values that you want to evaluate)

–This will return Apple
SELECT IIF(‘APPLE’ = ‘APPLE’, ‘Apple’, ‘Banana’)

–This will return Banana
SELECT IIF(‘APPLE’ = ‘Banana’, ‘Apple’, ‘Banana’)

Page 5 of 19

Powered by WordPress & Theme by Anders Norén