Testing using ConfigurationManager with .net core

.net core has moved away from web.config and app.config but realistically it’s a pattern that many projects will still want to follow. Fortunately there is help in the form of the System.Configuration.ConfigurationManager NuGet package. However, there is a snag when it comes to using this package with unit testing, it doesn’t work 😉 The problem is that it goes looking for a .config file related to the test host rather than your test project. I’m currently working around this with a quick static hack but the correct answer is to inject a new config. You can correct the path like this;

var myConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).FilePath;            
myConfig = myConfig.Replace("testhost.dll.config", "MyProjectTests.dll");
var config = ConfigurationManager.OpenExeConfiguration(myConfig);

Hope that helps.

Advertisements

How to Test async and await

This is one of those, “please stop forgetting this dummy” posts aimed at myself. When you want to test an asynchronous method implemented via the Task-based Asynchronous Pattern (TAP) don’t forget to change the default test method;

Default:

[TestMethod]

public void TestAsyncCall() { … }

to

[TestMethod]

public async Task TestAsyncCall() { … }

Poor mans ORM–how to easily persist data

Carrying on from my post about easily loading data from a database into a list, I thought I’d publish how to easily save the data from a list of objects into the database. It works by convention, so you need to create a stored procedure called <type name>_Save and provide an argument for each property you want to be saved.

        
public void <TCollection, TItem> Save(TCollection dataToSave) where TCollection : IList         
{             
  TCollection instance = (TCollection)Activator.CreateInstance(typeof(TCollection));             
  IList list = instance as IList;             
  if (list == null)             
  {                 
    throw new InvalidConstraintException("must provide an IList");             
  }              
  Type itemType = typeof(TItem);             
  string procedureName = string.Format("{0}_Save", itemType.Name);              
  SqlParameter[] commandParameters =                     
    SqlHelperParameterCache.GetStoredProcedureParameterSet(this.connectionString, procedureName);
  using (SqlConnection connection = new SqlConnection(this.connectionString))             
  {                 
    connection.Open();                 
    foreach (var item in dataToSave)                 
    {                     
      using (SqlCommand command = new SqlCommand())                     
      {                         
        command.Connection = connection;                         
        command.CommandType = CommandType.StoredProcedure;                         
        command.CommandText = procedureName;                          
        foreach (SqlParameter inputParam in commandParameters.Where(p => p.Direction == ParameterDirection.Input 
            || p.Direction == ParameterDirection.InputOutput))                         
        {                             
          string parameterName = inputParam.ParameterName.Replace("@","");                             
          object value = GetValue(item, parameterName);                             
          inputParam.Value = value;                             
          command.Parameters.Add(inputParam);                         
        }                         
        int rowsAffected = command.ExecuteNonQuery();                         
        System.Diagnostics.Debug.WriteLine("Called " + procedureName + ", rows affected: " + rowsAffected);
      }                 
    }
  }
} 

I hope you find the code useful, I’ve certainly found it a quick and easy way to prototype code

MVC does not find the controller

In a previous post I talked about using MVC’s controller injection to drop in DLLs that contain controller classes. It allows for a nice separation leading onto creating a composite UI. I was happily using this mechanism when it just refused to load a controller from an additional DLL. I still do not understand why it doesn’t work but my workaround is to override the ControllerFactory. Here is a quick example of this, please note I’ve hardcoded the condition for the sake of this example.

protected void Application_Start()         
{
  ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());
  AreaRegistration.RegisterAllAreas();
  RegisterGlobalFilters(GlobalFilters.Filters);
  RegisterRoutes(RouteTable.Routes);
} 
     
public class MyControllerFactory : System.Web.Mvc.DefaultControllerFactory
{
protected override Type GetControllerType(System.Web.Routing.RequestContext requestContext, string controllerName)         
{             
  if (controllerName == "Library")
  {                                 
    Type reflib = Type.GetType("LibraryUI.Library,LibraryUI");
    return reflib;                              
  }             
  return base.GetControllerType(requestContext, controllerName);         
  }              
} 

Note: setcontrollerfactory is a bit old school, should be using the IoC of choice…I’ll need to look into a bit more, but for now this works

Poor mans composite UI or separating out controllers in MVC3

I was looking to create a simple composite UI style application in Microsoft MVC3. What I want is a host MVC application that will compose its UI from other Controllers and Views packaged in other DLLs. The concept comes from autonomous components and SOA where a service owns not only its traditional business services but all the data and almost-all of the UI.

I thought I would be overriding controller builders, adding configuration, etc, etc, but actually this “poor-mans” variant is very easy. Here are the steps I followed;

  1. Create your Host MVC3 web application (Host.proj), for the sake of this example choose the Internet application so you get the default HomeController
  2. Create your satellite MVC3 controller by creating a standard class library project, called Satellite.proj
  3. Add a reference in Satellite to System.Web.Mvc
  4. Create a controller for your satellite, say MyController. Add an ActionResult such as;
  5.  
    public class MyController : Controller 
    { 
      public ActionResult MyInformation() 
      {
        return View("MyInformation2");
      }
    } 
  6. Create the View folders for your controller in the Satellite project, e.g. Views\My\
  7. Now for linking them together. I just added a project reference from Host to Satellite in order to grab the DLL. The Views are slightly harder, I used a post build event in the Satellite such as; xcopy “$(ProjectDir)Views” “$(SolutionDir)Host\Views” /E /R /Y
  8. That’s it. Just add some code to use the controller, such as placing the following in the index view;
  9. @Html.Action("MyInformation","My")
    

    Edit: Note you get errors complaining that ‘there is no build provider registered for the extension’ you need add a dummy web.config to the project, follow these instructions;
    Using Razor in a class library

nHibernate CreateQuery gotcha

As an nHibernate newbie I wasted a bit of time trying to get the Hibernate Query Language (HQL) CreateQuery function to work for me. Even the simplist query failed to work, e.g. I have a class MyEntity and I wrote something like;
session.CreateQuery("From MyEntity as myEntity")
 
then nHibernate would give me errors such as "in expected", or "uknown token as". I’d read a bit about problems where the mapping may not have been processed yet but that couldn’t be the case because I’d previously successfully loaded a MyEntity. However, it did prompt me to ask the SessionFactory for the metadata about MyEntity. What I spotted was the EntityName included, now obviously, the fully qualified name of; MyNamespace.Bla.Yada.MyEntity. Therefore the correct syntax is;
session.CreateQuery("From MyNamespace.Bla.Yada.MyEntity as myEntity")
 
I’ve yet to find a way to add namespaces to the query but at least the thing works now!
 
 
 

Great talk about ADO Data Services

Just finished watching a really could talk from Mix09 about ADO.NET Data Services. I’ve been wondering about where the business rules really fit with ADO.NET DataServices and the Entity Framework. This has gone a long way to helping me understand it, I really recommend it.