Dnn.platform: Dynamically compiled Web APIs don't resolve since DNN 9.4

Created on 1 Oct 2019  路  19Comments  路  Source: dnnsoftware/Dnn.Platform

Description of bug

When a system has WebApi controllers which are compiled dynamically - in our case 2sxc Apps can include .cs files which are compiled on the fly - they must be given to the .net framework for activation. This worked well till DNN 9.4, which accidentally broke this functionality because DNN 9.4 replaced the IHttpControllerActivator.

I already found out how to fix this.

Steps to reproduce

List the steps to reproduce the behavior:

  1. Create a DNN 9.2 and a 9.4.x and install 2sxc on both
  2. Add an app-module (2sxc) to a page and install the angular demo app from https://2sxc.org/en/apps/app/tutorial-angular-8
  3. In the UI, click on the WebAPI demo
  4. As you can see, it works in <9.4 and fails in 9.4.x

Result in Pre 9.4

image

Result in 9.4

image

Result in 9.4 with fix applied

image

Current result

In 9.4 the WebApi calls fail with this message:

{"Message":"No HTTP resource was found that matches the request URI 'http://dnn940rc1raw2.dnndev.me/API/2sxc/app/auto/live/api/simple/hello'.","MessageDetail":"No controller was created to handle this request."}

Expected result

This should work

Additional context

The solution is fairly simple, I believe @ahoefling should be able to confirm this.

Affected version

  • [x] 9.4.1 nightly build
  • [x] 9.4.0 latest supported release
  • [ ] 9.2 (not affected)

Affected browser

  • [x] all

Solution

The solution is to correct the code in the DnnHttpControllerActivator in DotNetNuke.Web. Here's the fix:
```c#
using DotNetNuke.Common;
using System;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Dispatcher;
using Microsoft.Extensions.DependencyInjection;

namespace DotNetNuke.Web.Api
{
public class DnnHttpControllerActivator : IHttpControllerActivator
{
public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
// first try to just get it from the DI - if it's there
return (IHttpController) Globals.DependencyProvider.GetService(controllerType) ??
// If it's not found (null), then it's probably a dynamically compiled type from a .cs file or similar
// Such types are never registered in the DI catalog, as they may change on-the-fly.
// In this case we must use ActivatorUtilities, which will create the object and if it expects
// any DI parameters, they will come from the DependencyInjection as should be best practice
(IHttpController) ActivatorUtilities.CreateInstance(Globals.DependencyProvider, controllerType);
}
}
}

```

Most helpful comment

@eXistenZe This was in a RC for more than 3 months, and others are already using it, we cannot reverse it at this time

All 19 comments

I reviewed the problem and the submitted Pull Request and left notes on the Pull Request. I politely disagree with the change and do not think that DNN should be responsible for managed generated code in this fashion. It will also prevent generated code from leveraging Dependency Injection which defeats the point of the original change.

Take a look at my review
https://github.com/dnnsoftware/Dnn.Platform/pull/3046#pullrequestreview-295980423

@iJungleboy Can you provide us a snippet/example of how you are using this in code? Just trying to get an understanding of the downstream implications, as the use-case isn't exactly clear.

@ahoefling I addressed your concerns in the pull request. I really believe this is extremely important, as it's just like aspx or theme pages - you also don't need to compile those before running DNN. This is the same just for WebApis

@mitchelsellers sure.

Background

2sxc allows users to easily create schema/data/template/code packages to basically build anything.

Trivial Use Case

In the trivial case - which many people are familiar with - people create schemas and some template pages to show that data. This is not what we're addressing here.

SPA Use Case

When people use 2sxc to create a SPA, they often need more capabilities than provided by the simple REST. For example, they may want to have custom code running on certain calls etc. This kind of API is created using source files (.cs) in the /api folder in 2sxc. This is the use case we're talking about. And it's also the case mentioned above with the angular 8 template application which only breaks on DNN 9.4.

Custom Forms Use Case

2sxc is also often used for custom forms, like https://github.com/2sic/app-mobius-forms. Such forms can be customized indefinitely, incl. what happens on saving. But this is only possible because the save-code is freely editable in the background.

Any Advanced Apps

Basically many advanced 2sxc apps use WebApi. Maybe to get some statistics, to make some changes, custom save-routines, or just for some special AJAX.

General

All this much more flexible and faster than with building DLLs, since the server never restarts and the distribution of the App is also much simpler, as 2sxc apps can easily be exported/imported without any problems. So this functionality is absolutely essential. Breaking it would severely limit 2sxc.

A short video explaining it more https://www.screencast.com/t/WQibFL6yx4on

First things first:

  • DNN 9.4 introduced breaking changes without warning
  • These changes makes 2sxc, one of the most used extensions in DNN environment, mostly unusable and without possible fix on their end.
  • Dynamically compiled Web APIs are an amazing feature for devs and non devs alike to do some magic with DNN. I would have no idea on how to build a DNN module (I tried), but I dable in 2sxc views and controllers enough to make some cool stuff, since it's so damn easy to do so.

I'm sure there's a good reason for this update and this specific change (I honestly don't understand a single thing you discuss in the pull request), but I do know that perhaps this change needs to be more reflected on the consequences we now know.

I suggest 9.4.2 (or a quick 9.4.1.1) to revert the change or temporarily accept the suggested fix until this issue can be properly accessed.

We are meeting on this later this week, there is a lot more to this than appears.

Also, this was not mentioned at all during the almost 3 months of Release Candidates. But regardless we will address this, in some manner, ASAP.

@mitchelsellers thanks for prioritizing this and reviewing it with the releasers :). I'll be on vacation starting in a few hours, so I will be offline for a week - sorry about that.

Closing this request, as the change does not align with the patterns & practices recommendations for the long-term planning and growth of the DNN Platform. All standard development practices are possible with the existing implementation. For the specific impact to 2sxc, the vendor will need to work around this limitation that is in place for standards and security, a possible solution for this has been included earlier in the communication chain on this pull request.

@iJungleboy I'm emailing you directly on this as well.

Is it out of question to postpone this change (or reverse it temporarily) further into DNN later developments, so that extention developers have time to adapt?

@eXistenZe This was in a RC for more than 3 months, and others are already using it, we cannot reverse it at this time

I agree with this decision, 9.4.0 is a feature release and this is a feature that was added with extensive documentation, examples, blog posts, etc. There was a good effort done to verify this was not a breaking change for all the module pipelines and good overall awareness for anyone to point out issue with this before it has been released for 3 months. So at this point in time and because any developer could already be using it, we cannot revert this now.

Ok. I have a working server on my home pc. Guess I can start testing beta versions.
Is it a paid job (beta testing)? :)

@eXistenZe I know it is a bit tongue in cheek with your comment, but NONE of us are paid for the work that is done for DNN Platform. It鈥檚 all volunteer

Don't know what that means, but I was kidding. Both DNN and 2sxc are free, so it's only fair to contribute.

@mitchelsellers & @valadas could you point me in the direction how dynamically compiled webapis would be done according to the mentioned best practices? The solution we had was IMHO best practice and I simply don't know a better way.
Many thanks!

@valadas BTW I don't really agree - my fix doesn't break anything, because it's only applied when the DNN 9.4 mechanism fails (returns null). Otherwise my fix doesn't do anything. So I can't see it breaking anything in production, as it only changes the behavior if something is broken.

@ijungleboy. We emailed you directly about why no

can we also be updated if a solution to this problem has been found?

@Scippy there was a new release of 2sxc that addressed this issue.

Was this page helpful?
0 / 5 - 0 ratings