Adventures on the edge

Learning new development technologies (2015 - 2018)
    "When living on the bleeding edge - you sometimes have to bleed" -BillKrat

ASP.NET MVC - Setting up an Area (beta7)

“The scenario that areas address is being able to partition your application into discrete areas of functionality. It helps make managing a large application more manageable and allows for creating distinct applets that you can drop into an application” -- Phil Haack  read more

Setting up an Area under ASP.NET MVC (beta7) is rather straight forward. 

  1. Apply the [Area(“YourArea”)] attribute to your controller
  2. Setup your Areas\<YourArea>\Views* folder comparable to normal views
  3. Configure an “areaRoute” in your Startup.Configure method.

* The following locations are searched for view files:
/Areas/<YourArea>/Views/Home/Index.cshtml
/Areas/<YourArea>/Views/Shared/Index.cshtml
/Views/Shared/Index.cshtml.

Note: My HomeController actually resides in a separate PocArea project.

AreaCode

ASP.NET MVC - Server.MapPath (beta7)

Server is currently not available under the new HttpContext but there are two ways to get the traditional MapPath results.  

  1. You can use the extension method MapPath for the IHostingEnvironment interface.
  2. You can retrieve the path from the IApplicationEnvironment instance.

Both of these are easily accessible via constructor injection, by placing them in the HomeController constructor as shown below you can easily extract the path you are looking for.

public HomeController(
IApplicationEnvironment appEnv,
IHostingEnvironment server)
{
var wwwRoot = server.MapPath("web.config");
var webConfig = new FileInfo(wwwRoot);
var isWebConfig = webConfig.Exists;

var svrPath = server.MapPath("Views/Home")
.Replace(@"\wwwroot", "");
var isDirSvr = Directory.Exists(svrPath);

var envPath = appEnv.ApplicationBasePath
+ @"\Views\Home";
var isDirEnv = Directory.Exists(envPath);
}
Code

ASP.NET MVC4 - Setting up Dependency Injection (Unity) Revised

Back in 2011 I wrote an article after studying Brad Wilson’s article on controllers; I based my UnityControllerFactory on his work; the controller factory is how you hook an IOC container into MVC 4.   It is possible that since 2011 there are newer/improved ways of doing this, but I opted to simply blow the dust off of old code, build a new ASP.NET MVC 4 website from Visual Studio 2012, plug in my old project, and update the article to help a fellow developer in this forum thread.

The following animated gif displays the output of this SOURCE CODE when you click on the refresh button in the browser.   Note that the page will default to the “Foo2” implementation upon startup because of the the following Web.Config setting:

<appSettings>
<add key ="DefaultFoo" value="Foo2"/>
AnimatedMVC4
Figure 1.  Refresh button being hit on Index page.
 

From that point on the AppSettings will be maintained in memory and can be updated as needed - in our case we use the AppSettings “DefaultFoo” setting to determine whether we are going to use Foo1 or Foo2 (they both implement IFoo).

In the source code you’ll find a Gwn.Library.Controller project, it contains the necessary framework components to quickly standup a MVC 4 website using Unity dependency injection - it also contains the mock classes (Foo stuff).   Lines 35 and 36 in the top pane of figure 2 are responsible for swapping out the implementation used by lines 22-30.

To setup a new project to utilize my Dependency Injection hook, it will take four steps:

  1. Create your ASP.NET MVC 4 website
  2. Right click on references and select Manage NuGet packages to install the Microsoft Unity IOC package.
  3. Add a reference to the Gwn.Library.Controller project
  4. Update the Controller and Global.asax classes with the content highlighted in yellow boxes.

That’s pretty much it - everything else is gravy after that.

MVC4Source

Figure 2 source code updates to applicable classes

The ControllerFactoryInitialize() method on line 28 in the bottom pane of figure 2 above is what “hooks” our UnityControllerFactory class into the framework.  

We can use a new RegisterTypes() override, provided by the HttpApplicationBase class, to register our implementation in the Unity container.   By default, registrations are “Transient” which means a new implementation is instantiated each request from the container.   We need AppSettings to be a singleton because it not only pulls in the AppSettings into a collection (which we only want to do once) but also permits us to update that collection programmatically so I use the following parameter:
    new ContainerControlledLifetimeManager()
to let Unity know it will be a singleton - it is not a singleton in the true sense (static class) but within the context that the same instance is always served up when requested.

With my AppSettings being a singleton I can now use the following code:
   AppSettings.SetSettings(DefaultFoo, toggleKey);
on line 36 of figure 2 (top pane) to update the value to a toggled state.

Note above on lines 35 and 36 (bottom pane) that I register two implementations of IFoo - I give them names that match their class names for convenience.  This allows me to to programmatically select the concrete class to use for the IFoo implementation by simply getting the current setting (which will be “Foo1” or “Foo2”). 

Reference the GetDefaultFoo() method below - I invoke the following:
    var configKey = _settings.GetSettings(“DefaultFoo”)
    var returnValue = _provider.Resolve<IFoo>(configKey); 

The first time I call this method the value will come from what was pulled in from the App.Config and subsequent use will come from any updates made to the AppSettings.          

using Gwn.Library.Controller.Interfaces;
using Microsoft.Practices.Unity;

namespace Gwn.Library.Controller.Mocks
{
public class FooFactory
{
private readonly IUnityContainer _provider;
private readonly IAppSettings _settings;

/// <summary>
/// Initializes a new instance of the FooFactory class.
/// Using construction injection to set the implementation
/// for IUnityContainer and IAppSettings
/// </summary>
/// <param name="provider">The provider.</param>
/// <param name="settings">The settings.</param>
public FooFactory(
IUnityContainer provider, IAppSettings settings)
{
_provider = provider;
_settings = settings;
}

/// <summary>
/// Gets the default foo based on Web.Config setting.
/// </summary>
/// <returns>IFoo.</returns>
public IFoo GetDefaultFoo()
{
// Get the "defaultFoo" setting from the Web.Config file
var configKey = _settings.GetSetting("DefaultFoo");

// Use named value to retrieve IFoo
var returnValue = _provider.Resolve<IFoo>(configKey);
return returnValue;
}
}
}

Note in our AppSettings constructor below that I pull the settings from the Web.config file into our _appSettings field.   The SetSettings will add or update collection values as applicable.
using System.Linq;
using System.Web.Configuration;
using Gwn.Library.Controller.Interfaces;
using System.Collections.Specialized;

namespace Gwn.Library.Controller.Implementation
{
public class AppSettings : IAppSettings
{
private readonly NameValueCollection _appSettings;
public AppSettings()
{
_appSettings = WebConfigurationManager.AppSettings;
}

public string GetSetting(string key)
{
return _appSettings.AllKeys.Any(k => k == key)
? _appSettings[key]
: "";
}

public void SetSetting(string key, string value)
{
if (_appSettings.AllKeys.Any(k => k == key))
_appSettings[key] = value; // Update
else
_appSettings.Add(key, value); // Add
}
}
}

ASP.NET MVC - how to get config.json settings (beta7)

This adventure involves creating an IAppSettings implementation that can survive versioning changes - we want a single entry point to get settings so that if something changes, we only have to update one class or create a new implementation.  Note in the image below (on line 100) that our implementation of IAppSettings is AppSettingsBeta7..

Finding how to retrieve the config.json settings was quite the challenge since the methods shown during research vary from version to version.
Adventures on the edge I had to pave the way on this one as I couldn’t find anything that worked under beta7

The short version is that you have to store an instance of the IConfiguration in the IOC container (line 99 in the image below).  You can then retrieve the settings from it as shown in the AppSettingsBeta7 class (source code further down in this article).

The long version is a proof of concept that has a setting in the configuration file (DefaultFoo) which will designate which implementation of IFoo that should be used.  First I started by creating two implementations of IFoo (lines 94 and 95 in the image below).  We’ll let our factory decide which implementation to use based on the value of “DefaultFoo” in our config.json file.  

Startup

Since I throw an exception on line 168 above if the wrong implementation of IFoo is used, I can operate on the premise that  “no news is good news” and everything is working if I get to my index page.

Our config.json file is configured to use the value of “Foo2” for DefaultFoo

{
"AppSettings": {
"DefaultFoo": "Foo2"
},
"Data": {
"DefaultConnection": {
"ConnectionString": "Server=(localdb)\\mssqllocaldb;Da...
}
}
}
In the Configure method in the above image we resolve our factory on line 159 which instantiates the class propagating the dependency chain via constructor injection (reference line 188 below) and then uses the factory to get the concrete implementation of IFoo.
 
This is where the IAppSettings implementation comes in - we need to use its GetSetting() method to retrieve the setting for “defaultFoo”.   Because I am coding against an interface, I can use IAppSettings throughout the application without concern about breaking changes in the future; the new implementation will handle it.

Foo

 

//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
// AppSettings
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
public interface IAppSettings { string GetSetting(string key); }

/// <summary>
/// Our application will code to IAppSettings since it is possible
/// configuration code will change - only this implementation will
/// have to be updated if required.
/// </summary>
public class AppSettingsBeta7 : IAppSettings
{
public const string APP_SETTINGS = "AppSettings";
private ConfigurationSection _section;

public AppSettingsBeta7(IConfiguration config)
{
_section = config
.GetSection(APP_SETTINGS) as ConfigurationSection;
}
public string GetSetting(string key)
{
var result = _section.Sources.Select(s =>
{
string value;

// Build the expected search key
var searchKey = string.Format("{0}:{1}", APP_SETTINGS, key);

// Try to get search key from IConfigurationSource
s.TryGet(searchKey, out value);

return value; // Return result
})
.Where(s => s != null);
// Only return non-null results

// Only get first or default if there are results
var returnValue = result.Any() ? result.FirstOrDefault() : "";
return returnValue;
}
}


The GetSetting() method above demonstrates “a way” to retrieve the config.json settings for beta7.   Note that it has a dependency on IConfiguration which is not set in the container by default - we had to add it as a singleton in the Startup class method ConfigurationServices.

Also note that we get our configKey from the config.json file and then we send it as a named parameter to the provider’s Resolve() method. 

var configKey = _settings.GetSetting("defaultFoo");
var returnValue = _provider.Resolve<IFoo>(configKey);


This is not actually a beta7 syntax for the built-in dependency injection (DI) container, I am use to Unity IOC (which I am now abandoning since Microsoft did) but liked the syntax so I’ll hold on to it - at least for now.   I used the following extension methods to emulate Unity’s Resolve<> method:
 

//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

// ServiceProvider
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

/// <summary>
/// Used to Unity - will emulate its syntax
/// </summary>
public static class IServiceProviderExtension
{
public static T Resolve<T>(this IServiceProvider provider)
{
var result = provider.GetService(typeof(T));
return (T)result;
}
public static T Resolve<T>(
this IServiceProvider provider, string key)
{
// Wee bit of a hack - we'll use the class name as the key
var result = provider
.GetServices<T>()
.Where(s => s.GetType().Name == key);


if (result.Any<T>())
return result.FirstOrDefault();
return default(T);
}
}


Below are all of the code bits for IFoo and its implementation as you can see I am expecting the message “I am a foo too!” because I use Foo2 to implement IFoo based on the config.json file setting of “DefaultFoo”:

//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

// Foo stuff
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
public interface IFoo { string GetFooMessage(); }

public class Foo1 : IFoo { public string GetFooMessage() {
return "I am a foo!"; } }

public class Foo2 : IFoo { public string GetFooMessage() {
return "I am a foo too!"; } }

public class FooFactory
{
private IServiceProvider _provider;
private IAppSettings _settings;

public FooFactory(
IServiceProvider provider, IAppSettings settings)
{
_provider = provider;
_settings = settings;
}
public IFoo GetDefaultFoo()
{
// Get the "defaultFoo" setting from the config.json file
var configKey = _settings.GetSetting("defaultFoo");

// Use it to get a named value (where name is implementation)
var returnValue = _provider.Resolve<IFoo>(configKey);
return returnValue;
}
}


ASP.NET MVC - RenderViewToString in MVC 6

The plumbing has changed with ASP.NET MVC 6 requiring us to think differently, particularly with inversion of control (aka dependency injection) now being a first class citizen.

In my latest adventure, my goal was focused on building a reusable class that allows me to convert a View into a string. This can be used for generating emails, newsletters, or insertion into other views.

To achieve this objective, I dug into the ASP.NET MVC source code to see how it works under the hood (reference blog “how to setup for using / debugging open source code”). To make this work I had to find the parameters required by the view engine’s FindView method and the view’s RenderAsync method.

I then created a new MVC website to prove out the code and updated the HomeController so that the About view injected the Contact views content:

Output

The about.cshtml view was updated to display the raw data provided by the HomeController (line 10 in image below).

AboutView

With the view done, I complied with the following steps within the HomeController class:

  1. Paste the ViewHelper class code into the HomeController (source available at end of this blog)
  2. Update the HomeController constructor so that dependency injection will resolve the ViewHelper via constructor injection (and as a result, its dependencies)
  3. Update the About() method to set ViewData[“Contact”] with the rendered content of the Contact view (on line 65-66 below).

ControllerSource

Perhaps the most important and final step is to ensure the dependency injection container knows about the ViewHelper - this is done on line 49 below in the Startup.ConfigureServices() method.

Ioc

 

public class ViewHelper
{
private IRazorViewEngine _viewEngine;
private ITempDataDictionary _tempDataDict;

public ViewHelper(
IRazorViewEngine viewEngine,
ITempDataDictionary dataDict,
IHtmlHelper helper)
{
_viewEngine = viewEngine;
_tempDataDict = dataDict;
}

public string RenderToString(
string viewName,
ActionContext actionContext,
ViewDataDictionary viewData)
{
using (var stringWriter = new StringWriter())
{
var viewEngineResult =
_viewEngine.FindView(actionContext, viewName);

var viewContext = new ViewContext(
actionContext,
viewEngineResult.View,
viewData,
_tempDataDict,
stringWriter,
new HtmlHelperOptions());

viewEngineResult.View.RenderAsync(viewContext);

var result = stringWriter.GetStringBuilder().ToString();
return result;
}
}
}