1

The goal is to create ASP.NET MVC Plugins. I have it all working as I want, except I cannot get different versions of the same plugin to play nicely together when it comes to the Views. Everything else is working fine; including paths to the different views.

Each plugin has 2 projects, a class library, and a web project that references the class library.

In the web project I have this view:

 @model MyPluginClass
<p>Hello from the View</p>

But when running the view, I get

The type 'MyPluginClass' exists in both 'MyCompany.Plugin.Default.v1.0, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' and 'MyCompany.Plugin.Default.v1.1, Version=1.1.0.0, Culture=neutral, PublicKeyToken=null'

To get the different view paths to exist for each version, I created a custom PluginRazorViewEngine that inherits from RazorViewEngine

public PluginRazorViewEngine(PluginType pluginType, string pluginCode, decimal version, IViewPageActivator viewPageActivator) : base(viewPageActivator)
    {
        var viewLocationPrefix = "~/Plugins/";
        viewLocationPrefix += pluginCode + " v" + version.ToString("N1");
        ViewLocationFormats = new[]
        {
            viewLocationPrefix + "/Views/{1}/{0}.cshtml",
            viewLocationPrefix + "/Views/Shared/{0}.cshtml"
        };
        MasterLocationFormats = new[]
        {
            viewLocationPrefix + "/Views/{1}/{0}.cshtml",
            viewLocationPrefix + "/Views/Shared/{0}.cshtml"
        };
        PartialViewLocationFormats = new[]
        {
            viewLocationPrefix + "/Views/{1}/{0}.cshtml",
            viewLocationPrefix + "/Views/Shared/{0}.cshtml"
        };
        FileExtensions = new[]
        {
            "cshtml"
        };

    }

The plugins must be loaded in a Plugins Folder structure in the website as follows

Plugins/Default v1.0/ dlls go here
Plugins/Default v1.0/Views
Plugins/Default v1.1/ dlls go here
Plugins/Default v1.1/Views

I use a PostApplicationStartMethod to then load the view engine

    var engine = new PluginRazorViewEngine(PluginType.Label, Settings.PluginCode, Settings.Version);
            ViewEngines.Engines.Add(engine); // want to add the engine to the end not the start

            var routeNamePrefix = Settings.PluginCode + "_v" + Settings.Version.ToString("N1") + "_";

            var routePrefix = Settings.PluginCode + "/" + Settings.Version.ToString("N1") + "/";




            RouteTable.Routes.MapRoute(
                routeNamePrefix + "Default",
                routePrefix + "{controller}/{action}/{id}",
                new
                {
                    action = "Index",
                    id = UrlParameter.Optional

                },
                new[] { "MyCompany.Plugin.Default.Web.Controllers" }
            );

NOTE: I loaded this using reflection from the class library, as again the PostApplicationStartMethod played happily with the class library, but on the web project the PostApplicationStartMethod always ended up referencing the v1.0 assembly and v1.1 assembly got ignored. It is like class libraries work with versioning and web projects just do not.

Anyhow, is there any way of getting the RazorViewEngine to use the correct assemblies for each version short of changing the namespaces?

I thought of using RazorGenerator, but the virtual paths don't work with what I want to do.

And am not sure if Signing the assembly would solve all problems. But if I went down that route, it looks like I would need to strongly sign all the projects which am not that keen to do.

To version the assemblies, I am changing the assembly name MyCompany.Plugin.Default.Web.v1.1 and the assembly version and file version to 1.1.0.0

Any thoughts?

Sylvia
  • 1,022
  • 9
  • 20
  • This is a feature of the .NET runtime. I believe you would have to create a new AppDomain to load two different assembly versions (see https://stackoverflow.com/questions/4451220/loading-multiple-versions-of-the-same-assembly). No idea if that is possible in ASP.NET MVC. But why would you need the old version anyway? – Greg Aug 06 '18 at 12:37
  • Hi @Greg The plugins are actually quite complicated, and we will need to version them occasionally, where we want some clients to stay on 1 version, but other clients to upgrade to the newer version. The views are just maintenance screens for the plugins, but it is likely that if the plugin is versioned, that the views will also be different. Argh if it not possible. Will look into the AppDomain. – Sylvia Aug 06 '18 at 12:58
  • I understand you want to test both versions, but why would a client want to use version 1 and 1.1 simultaneously? Won't 1.1 supersede 1? – Greg Aug 06 '18 at 13:07
  • We have many different clients on the same system. Some will not want the newer version. – Sylvia Aug 06 '18 at 13:41
  • In the end, it didn't seem possible, :-( – Sylvia Aug 09 '18 at 07:32

0 Answers0