Analysis

Workaround for Relative Path / Base URL mismatch on Visual Studio 2012 and Hosting on IIS


This post deals with how we can use relative paths in a .NET web project ( Single Page Application using AngularJS and Bootstrap for cosmetics, ASP.NET MVC4 for hosting WebAPIs and providing initial view.) and make it working properly both when running from Visual Studio as well as after hosting on a Remote Server (IIS). There was a lot of trial and error as well as research carried on to find a sleek solution for this problem. I’m not mentioning each and every bit of it, Let’s jump straight in to the main issues encountered.

There were three areas in which I wanted to use relative paths.

  1. Linking scripts and styles
  2. Ajax calls
  3. Angular routes

For the first one, that is for linking scripts, I got the solution easily which is using  tilde(‘~’) character as prefix as shown below.

<script src="~/Scripts/App.js"></script>

But the second and third apparently didn’t seem to support that solution, So I had to think of some other alternatives. After some research the solution got was to use a base url using the base tag in head node of my Home/Index page.

<base href="/MyApp/"/>

Note: You have to use ‘/MyApp/’. MyApp/ or /MyApp will not work.

In angular js routes I defined it like templateUrl:’Partials/Main.html’ as using slash before will cause it to search in the root folder in IIS. Ajax call urls are given like $http.post(‘api/mymodule/myaction’).

The problem with adding a base URL is that although it works fine in deployment, it breaks in Visual studio as there is no virtual directory with that name. Which means I need a different version of Index.html after publishing. I need the base tag only in published location.  I need to runs some operations post publish to change the source. For this purpose I added the following code in my project file.

  <UsingTask AssemblyFile="bin\PublishTasks.dll" TaskName="PublishTasks.AddBaseURL" />
 <Target Name="CustomTarget" AfterTargets="CopyAllFilesToSingleFolderForPackage"  >
    <AddBaseURL FilePath="$(_PackageTempDir)\Views\Home\Index.cshtml"  BaseURL="/MyApp/">
      <Output TaskParameter="Result" PropertyName="BaseResult" />
    </AddBaseURL>
    <Message Importance="high" Text="Result: $(BaseResult)" />
  </Target>

The first line is for adding the custom task I created to the project.  Find its code below.

namespace PublishTasks
{
    public class AddBaseURL : ITask
    {
        public string BaseURL { get; set; }
        public string FilePath { get; set; }

        [Output]
        public string Result { get; set; }

        #region ITask Members

        public IBuildEngine BuildEngine { get; set; }

        public bool Execute()
        {
            try
            {
                HtmlDocument htmlDoc = new HtmlDocument();
                htmlDoc.Load(FilePath);

                HtmlNode head = htmlDoc.DocumentNode.SelectSingleNode("/html/head");

                HtmlNode baseTag = htmlDoc.CreateElement("base");
                HtmlAttribute href = htmlDoc.CreateAttribute("href");
                href.Value = BaseURL;
                baseTag.Attributes.Add(href);
                head.AppendChild(baseTag);
                htmlDoc.Save(FilePath);
            }
            catch (Exception e)
            {
                Result = "Add BaseURL Error:" + e.ToString();
                return false;
            }

            Result = "Added Base url successfully.";
            return true;
        }

        public ITaskHost HostObject { get; set; }

        #endregion
    }
}

Here I implemented the ITask class to create a custom task. You can find the documentation regarding tasks in Microsoft website. It is having two arguments, FilePath and BaseURL which is given in the project file code above. You can also see that I have used HTMLAgilityPack for easy access of HTML file.

$(PackageTempDir) points to a temporary folder where all projects before publishing is copied to. So, If we edit the file there, it will be reflected in the publish folder as it gets copied. A custom target is used with AfterTargets set to CopyAllFilesToSingleFolderForPackage. The target “AfterPublish” was not working due to a bug in Visual Studio. Now, when we publish after setting the logging level to diagnostic, you can see the following in build log.

2> Using "AddBaseURL" task from assembly "...\PublishTasks.dll".
 2> Task "AddBaseURL"
 2> Task Parameter:FilePath=obj\Release\Package\PackageTmp\Views\Home\Index.cshtml
 2> Task Parameter:BaseURL=/MyApp/
 2> Done executing task "AddBaseURL".
 2> Task "Message"
 2> Task Parameter:Importance=high
 2> Task Parameter:Text=Result: Added Base url successfully.
 2> Message: Result: Added Base url successfully.
 2> Done executing task "Message".

Now, that’s a long fix for a simple issue!

Advertisements

Unit testing a C++/CLI Wrapper


Normally the software projects I worked in never consisted of a proper unit testing phase. What we did all these years was not UT but IT ( integration testing ). Some people still oppose when I say you can’t unit test a code without completely isolating the method under test. This is probably due to their lack of knowledge or something related to the rocket science that I still don’t know. In either case, I love to direct them to this one book called “The art of Unit Testing by Roy Oshervoe”. In one project, I got an opportunity to study about unit testing and submit a report on whether it is feasible under the current workflow.The knowledge gained from that particular assignment, I consider precious.

What I’m going to talk about is not about unit testing in general. I suggest you to take a look at that book I mentioned to get a good picture of current unit testing methods etc; Ignore if you already know. During my assignment, while trying out different techniques like dependency injection in my project scenario, I come across a difficult situation. I was testing a C++/CLI wrapper for a module in C++.  Its basically an adapter that marshals the native C++ types in to corresponding C# types and vice versa. Wrappers normally have little or less logic. But, there are some ‘if’s and ‘while’s involved even though that counts as the conversion logic only. To ensure nearly a complete code coverage, I need to test those minute details too. Dependency to the module that is being wrapped is obvious. I need to get rid of it in order to test it.

A typical C++/CLI Wrapper

A normal dependency breaking scenario consists of two classes that are coupled together that we use inversion of control(IoC) to loosen the coupling. IoC is a process by which the assembler binds the object coupling at run-time. Normally we achieve this through Dependency Injection, where the interface or base class of the dependent class is injected via the constructor or setter functions.

We can refactor the code so that the class under test uses an interface that is added to the top of the dependent class in the hierarchy. During testing, the interface can be replaced with a stub class in order to isolate the function of the class to be tested from the dependency. But, what if such a re-factoring is not possible from the dependent side? What if we are using a class from a library that cannot be modified? In the case of our CLI wrapper the dependency was from a c++ library which should not be modified. So introducing an interface or a base class above the hierarchy is not easy.

After some (re)search I found out a solution that is appropriate while considering the clarity and definitely not, the complexity. It suggested the introduction of yet another wrapper to the low level dependency that delegates the functions that the high level code uses. So in our case if the class Engine is a low level class where we cannot introduce an interface above it, we can add the class EngineWrapper that wraps the functions of Engine and we can add an interface IEngineWrapper above it. So, the EngineCLIWrapper must keep only the interface and accept the instance via a constructor or a setter function. The unit testing class EngineCLIWrapperTest breaks the dependency by deriving a stub class from the wrapper interface and “injecting” it to the instance of class under test.

Dependency injection for unit testing.

Virtual keyword!

The previous solution looks pretty good, but if I am to implement this, I will certainly feel a guilt of over-decoupling. We created an IEngineWrapper interface only to be implemented by a wrapper that points to the actual dependency. Was all these necessary? The answer would be YES if the dependency is towards non-virtual methods. As the only objective was to test the CLI wrapper, I had this question in my mind about the inclusion of an adapter to an adapter for sake of unit testing. Luckily the dependency was towards some virtual functions of the low-level class. After spending some thought a I could think of a simple solution to this problem to be specific. The Idea is to subclass the original “low-level” dependent class, stub or mock it by overriding the dependent virtual function so that it poses no menace while unit testing. Now, even though the c++ class Engine does not have any virtual functions, we can make the wrapper functions of EngineWrapper virtual and derive a stub directly from it instead of using IEngineWrapper as shown below.

Simplified approach for easy stubbing/mocking.

I’m not sure whether this is a correct approach or not, but I believe I spent some seat time in sorting this out. Do chip in your valuable suggestions/opinions. In other news, when I started this post, I was thinking that I invented a new dependency breaking method but ended up wall bashing when I realized that I forgot about the ‘virtual’ keyword. Silly me!