Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Binding redirect support #992

Closed
mamaso opened this issue Nov 27, 2016 · 168 comments
Closed

Binding redirect support #992

mamaso opened this issue Nov 27, 2016 · 168 comments

Comments

@mamaso
Copy link
Contributor

@mamaso mamaso commented Nov 27, 2016

Per this customer issue:

http://stackoverflow.com/questions/40816285/azure-functions-with-nuget-packages-that-have-different-versions-of-the-same-dep#

@fabiocav
Copy link
Member

@fabiocav fabiocav commented Nov 28, 2016

This is a known limitation and, with the current design, not something that can be easily addressed. I'm adding a comment in the SO question as the root cause is not directly related to redirects.

@lindydonna lindydonna added this to the backlog milestone Nov 28, 2016
@paulbatum paulbatum changed the title Better binding redirect support Binding redirect support Mar 20, 2017
@jorupp
Copy link

@jorupp jorupp commented Mar 30, 2017

Is there another way to work around the issues binding redirects are usually used for? For example, I want to use the WebJobs nuget package, which requires 7.2.1 or higher of WindowsAzure.Storage. However, 8.1.1 is out, which updates a bunch of stuff, including adding support for block blob uploads. Then, when I declare a function as taking in a IQueryable<DynamicTableEntity>, I'm stuck - if I reference the 8.1.1 version to get the functionality I want, I get an error at function bind time that it DynamicTableEntity doesn't implement ITableEntity.

Or is there another way to achieve this besides binding redirect support?

@Blackbaud-MitchellThomas

Is this worth looking at, @jorupp?

https://blogs.msdn.microsoft.com/appserviceteam/2017/03/16/publishing-a-net-class-library-as-a-function-app/

The development experience using this approach has been so much better for me.

@jorupp
Copy link

@jorupp jorupp commented Mar 30, 2017

@Blackbaud-MitchellThomas - it has the same basic issue - no binding redirects. In fact, I hadn't run into the issue myself until I switched to that approach yesterday and updated all my nuget packages to the latest (since I had the package GUI to tell me about it). I got binding errors because the latest Microsoft.Azure.WebJobs needed an older version of WindowsAzure.Storage, and didn't recognize the 8.1.1 types as matching the 7.2.1 types it had loaded (since there was no binding redirect to force them to both load the 8.1.1 types).

@Blackbaud-MitchellThomas

That's good to know that it's still a potential gap. I have a project running in that format, and it cleared up my flavor of these issues. But my problem was that it was erroring looking for a given .dll and couldn't find it, so I had been able to figure out to supply it with the csx file.

@christopheranderson
Copy link
Member

@christopheranderson christopheranderson commented Apr 3, 2017

Blocked on this work: #1319

@jorupp
Copy link

@jorupp jorupp commented Apr 3, 2017

Could there be a way to work around this temporarily by providing the data on what version of an assembly to use in another form (ie. JSON file) and handling the AppDomain.AssemblyResolve event? Just thinking out loud here.

@danielmackay
Copy link

@danielmackay danielmackay commented Apr 17, 2017

Is there any possible work around for this? We have just tried to migrate from web jobs to functions, but our application depends on Micosoft.Owin.Security 3.1.0.0, but internally Asp.Net Identity depends on Micosoft.Owin.Security 2.1.0.0. We cannot migrate to functions as we would like to until this is supported.

@RudyCo
Copy link

@RudyCo RudyCo commented Apr 27, 2017

This is a major issue. How can Microsoft state that Azure Functions are ready for use in production environments with such limitation?

@fabiocav
Copy link
Member

@fabiocav fabiocav commented Apr 28, 2017

@jorupp that is one possibility we have considered (we already perform a a fair amount of custom resolution). The the work planned in #1319 will address this in a better and more consistent (not Azure Functions specific) way.

In the meantime, an approach that will usually address this need is to place the assembly you wish to use in a bin folder, in the function folder. The runtime will use this location as a fallback when probing for assemblies.

@jnevins-gcm
Copy link

@jnevins-gcm jnevins-gcm commented Apr 28, 2017

That doesn't work. If a strong named assembly is already loaded into the appdomain by azure functions, it will always use that one before loading a new assembly and will then throw a manifest mismatch error for any strong named assembly

@jnevins-gcm
Copy link

@jnevins-gcm jnevins-gcm commented Apr 28, 2017

I think this is just a fundamental design problem in how azure functions were thought out. As a suggestion, the best thing I can think of is for azure functions to handle ALL assembly resolve events and have NO assemblies in any internal bin folders, loading all assemblies from byte arrays to ensure a "no load context" for all assemblies. Assembly resolve can then handle multiple versions of the same assembly loaded into a single app domain

@jnevins-gcm
Copy link

@jnevins-gcm jnevins-gcm commented Apr 28, 2017

Basically prevent any loading of any assemblies by the .net runtime itself, as assembly resolution in .net is a total mess anyway

@fabiocav
Copy link
Member

@fabiocav fabiocav commented Apr 28, 2017

@jnevins-gcm that (as mentioned) doesn't work in all scenarios, but is a viable fallback for some. Much of what you suggest above is actually how things are handled (for example, private assemblies are loaded from byte arrays, without a load context, and side-by-side loading is supported), the Azure Functions assembly resolver establishes a function scoped context and bypasses the .NET loader in those scenarios, and the bin folder mentioned above is not the application bin folder, but the function scoped one (where assemblies are loaded using the method described above).

The details on how this work are a bit more complex, and there are scenarios where we must load assemblies differently, but if using private assemblies only, the workaround above works as described.

We are working on the longer term solution for this that will provide behavior consistent with a "regular" .NET application, but this is still a bit out.

@jnevins-gcm
Copy link

@jnevins-gcm jnevins-gcm commented Apr 28, 2017

I saw that work item. It seems like a very very bad idea. You're basically describing building a new remoting protocol.

The workaround doesn't work as described though, unless you're loading all the dlls ahead of time in the bin dirs irrespective of name, in which case one could name each conflicting dll according to its version. Is that the case?

@jnevins-gcm
Copy link

@jnevins-gcm jnevins-gcm commented Apr 28, 2017

*implementation not protocol

@fabiocav
Copy link
Member

@fabiocav fabiocav commented Apr 28, 2017

@jnevins-gcm I'll try to put some documentation better describing this process and also the scenarios I'm referring to (I've been meaning to do that for a while).

For the out-of-proc issue, there are a lot of details missing there as well, and we're trying to update it so everything is out in the open and we can get more feedback, but the scope is significantly larger than just trying to run .NET in isolation.

I'll work with @christopheranderson to have more details on that issue so we can better discuss the approach.

@nickverschueren
Copy link

@nickverschueren nickverschueren commented May 1, 2017

I'm trying to reference a NetStandard library in my function and I'm getting:
mscorlib: Exception has been thrown by the target of an invocation. IoT.EuriSmartOfficeFunc: Could not load file or assembly 'System.Runtime, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies
This is probably due to this issue, because actually version 4.1.1.0 is deployed. Is there any way at the moment to get this assembly redirected?

@fabiocav
Copy link
Member

@fabiocav fabiocav commented May 1, 2017

@nickverschueren what version of the runtime are you running against? (Here's how to check)

If you're running on anything below 1.0.10917, please restart your Function App and try again (if you find you're running on 10917, please also retry as it was just released)

@npiasecki
Copy link

@npiasecki npiasecki commented May 2, 2017

After having played with a few small functions, I started porting one of our existing applications that has a component that's a Windows service that runs Quartz cron jobs over to Azure Functions as a precompiled assembly. I ran into an issue where one assembly is referencing log4net 2.0.8 but Microsoft.ApplicationInsights.Log4NetAppender is referencing log4net 2.0.5.

Since I can't do a binding redirect, I guess my options are to recompile the AI appender with 2.0.8, recompile the reference to downgrade to 2.0.5, or just give up and revert to WebJobs?

Recompiling in this particular case isn't a huge problem, but the lack of binding redirect support kind of makes Azure Functions a ticking time bomb when it comes to maintenance and gives me some serious pause. Is there any kind of timeline for when binding redirects will be supported?

@marcothz
Copy link

@marcothz marcothz commented May 2, 2017

+1

@flagbug
Copy link

@flagbug flagbug commented May 2, 2017

Without binding redirects, Azure Functions with precompiled assemblies is basically impossible to use, as soon as you want to use an external NuGet package

@flagbug
Copy link

@flagbug flagbug commented May 2, 2017

After some playing around, I've solved this by using ILRepack/ILMerge, to merge all the problematic dependencies into the main assembly. This seems to have solved the binding redirect issues

@BowserKingKoopa
Copy link

@BowserKingKoopa BowserKingKoopa commented Jul 25, 2018

Any update on this? What's the current state of Azure Functions with regard to using the dlls I give it instead of crashing? https://github.com/Azure/azure-functions-host/wiki/Assembly-Resolution-in-Azure-Functions hasn't been updated in a while.

@fabiocav
Copy link
Member

@fabiocav fabiocav commented Jul 25, 2018

@BowserKingKoopa we've been covering the updates on the preview release announcements. Most of the enhancements mentioned on that document are now live in the 2.0 preview. The vast majority of the binding issues have been addressed, with a couple of additional fixes coming as part of a larger set of changes to address storage dependencies.

Please give that a try and let us know if you run into any issues.

@MisinformedDNA
Copy link

@MisinformedDNA MisinformedDNA commented Jul 26, 2018

@BowserKingKoopa I've been using v2 with no binding problems.

@devedse
Copy link

@devedse devedse commented Jul 30, 2018

@fabiocav, Is there a description available somewhere on how to do binding redirects with Azure Functions? Or will it all just magically work if there's a newer version of the DLL loaded then the one explicitly referenced?

@Joehannus
Copy link

@Joehannus Joehannus commented Jul 30, 2018

@devedse
As I mentioned above we've had our share of binding issues as well - and I got the following link on how to do binding redirects in another thread (in this one: Azure/azure-amqp#110):
https://docs.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/runtime/bindingredirect-element

I implemented this (using an app.config) in our azure function project. And it worked accordingly, solving all our issues. I don't know though whether this this a supported feature?

@fabiocav
Copy link
Member

@fabiocav fabiocav commented Jul 30, 2018

@devedse there is no explicit binding redirect support. Redirects and unification are done implicitly by the runtime, using a few different sources of information depending on the model (e.g. your published artifacts, deps files and extensions registrations). So the short answer is that, in 2.0, it should "just work" without any additional steps.

@paulbatum
Copy link
Member

@paulbatum paulbatum commented Jul 30, 2018

@Joehannus I would like to dig a little further into your question, as I'm surprised that you were able to resolve this type of problem with an app.config within your function app project, but it might be due to me overlooking some important factors.

I would prefer to not dive into the details here as this thread is already very long. Do you have a minimal, standalone repro that demonstrates how adding the app.config resolves the issue? If so, it would be great if you could file a separate issue (in this repo is fine) with the repro details and at me there so I can look further.

@Joehannus
Copy link

@Joehannus Joehannus commented Jul 31, 2018

@paulbatum the reason I've tried this is that somebody on a different thread gave me that advice (Azure/azure-amqp#110). I've had lots of issues with the Azure.Devices libraries, either to get specific functions to be called, or even to get functions started at all due to binaries that could not be resolved - and after adding the app.config it seemed as if the starting issues were solved. But I've tried so many combinations of packages versions, to get multiple functions to run correctly, that solving the start issues just might have been coincidental, and that it was not due to the app.config.

To test this I've just installed the latest versions of all packages, and also removed the app.config. And the functions still run without issues. So it looks that it indeed was coincidental.

@MisinformedDNA
Copy link

@MisinformedDNA MisinformedDNA commented Jul 31, 2018

@fabiocav I can't remember any statement that this issue would ever be resolved on V1 and given that binding redirects work in V2, what is still left before we can close this issue?

@f2bo
Copy link

@f2bo f2bo commented Jul 31, 2018

While the V2 enhancements are welcome, they require that all dependencies be supported under .NET Core. We currently require dependencies that only target the .NET Framework and cannot be used in V2, as well as other dependencies that currently fail to load under V1 due its assembly resolution restrictions, which means that we cannot use either V1 or V2 successfully. We have a (brittle?) workaround for V1 based on AppDomain.AssemblyResolve, but there are still certain things that we cannot do, for example, use an ILogger instead of a TraceWriter in our Functions.

I have an open issue with more details here.

And a PR to the functions-assembly-loading-catalog here.

@paulbatum
Copy link
Member

@paulbatum paulbatum commented Jul 31, 2018

For the purposes of the discussion on this particular github issue, I think it would be helpful to exclude scenarios that involve a library that does not support .NET Core. If you are curious about the advice I gave @f2bo, see this comment.

For further discussion of scenarios where Azure Functions V2 would run on .NET Framework and allow you to use libraries that don't support .NET Core, see here:
Azure/Azure-Functions#790

@paulbatum
Copy link
Member

@paulbatum paulbatum commented Jul 31, 2018

@Joehannus thanks for getting back to us! I am really glad to hear that those packages are working for you on Functions V2 without any further configuration/changes.

@paulbatum
Copy link
Member

@paulbatum paulbatum commented Aug 13, 2018

Just a small update. We are wrapping up changes that will address one of the remaining assembly loading issues that we are tracking for V2 GA which is providing flexibility around which version of the Azure Storage SDK you can reference. The release that will have this change has been announced here:
Azure/app-service-announcements#129

What this change does is move Azure Storage bindings into an extension, similar to everything else. This will allow for multiple versions of the storage extension to exist, each referencing a different major version of the Azure Storage SDK. You pick which version you reference in your function app based on your needs.

I should note though, we will be starting with Azure Storage SDK 9.x and do not plan on publishing RTM releases of this extension that target earlier major versions (such as 7.x or 8.x). We will of course publish a new version of the extension when the Azure Storage team releases a new major version of their SDK.

@Szer
Copy link

@Szer Szer commented Aug 14, 2018

What this change does is move Azure Storage bindings into an extension, similar to everything else.

@paulbatum
I've just tested FSharp.Core 4.5.2 (newest release) and it works! (ValueOption, Map.TryGetValue)
AFAIK it was pinned in V2 runtime with 4.2.3 version.

Was it upgraded to latest or it works the same way as Azure Storage?
May I just upgrade FSharp.Core or Newtonsoft.Json as I wish?

@forki
Copy link
Contributor

@forki forki commented Aug 14, 2018

Regarding FSharp.Core: this was solved in: #2881 (comment)

@fabiocav
Copy link
Member

@fabiocav fabiocav commented Sep 27, 2018

With Azure Functions 2.0 reaching General Availability, we have now completed the work to have this issue resolved for production workloads.

We truly appreciate all the reports, repros and patience while we worked on this during the preview.

@fabiocav fabiocav closed this Sep 27, 2018
@solvingj
Copy link

@solvingj solvingj commented Sep 27, 2018

Really impressive work!

@pinaki1234
Copy link

@pinaki1234 pinaki1234 commented Jun 27, 2019

Seems I am having issues referencing functionalities in a Class Library from Azure function project. Has anyone in this thread run across this issue till now?

@fabiocav
Copy link
Member

@fabiocav fabiocav commented Jun 27, 2019

@pinaki1234 can you please open a separate issue with the details of what you're seeing and your current setup? That would help us better understand the issue you're running into. Thanks!

@Azure Azure locked as resolved and limited conversation to collaborators Jun 27, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet