Azure / Azure-Functions

1.11k stars 195 forks source link

Add support for authoring Azure Functions as .NET Core class library #805

Closed pscholtes closed 5 years ago

pscholtes commented 6 years ago

Add support to the "Azure Functions and Web Jobs Tools" extension within Visual Studio for authoring Azure Functions as a .NET Core class library. This issue is a spin off from a conversation started in #686 and is possibly, semi-related to #790.

When creating a new Azure Function app, you must select between the versions "v1 (.NET Framework)" or "v2 (.NET Standard)".

  1. If v1 is selected, you can target any version of the .NET Framework <= 4.6.1
  2. If v2 is selected, you can target any version of .NET Standard <= 2.0

Neither option allows the resulting Azure Function project to target .NET Core 2.x.

Scenario Given the following VS solution/project architecture for Company Xyz:

Problem When a project reference is added from Xyz.Functions to Xyz.Common Visual Studio generates a "project not compatible" build error as these two projects reference different frameworks (i.e. .NET Standard != .NET Core).

Reasoning In a "real word" enterprise-level application, it's a very realistic expectation for a developer to centralize the logic for a specific processing routine and want to leverage that code from an IActionResult in a MVC app and a [TestMethod] in a MSTest project. Continuing with that approach, AF should allow a developer to leverage their .NET Core code from a Trigger as well.

paulbatum commented 6 years ago

Some of the discussion in this issue is relevant - it provides steps that can get a function app with target netcoreapp2.0 compiling, but not running: https://github.com/Azure/azure-functions-vs-build-sdk/issues/160#issuecomment-386402717

This is the error you'll get if you try this: image

It would be good to understand whether we expect to be able to get this working. I don't understand the details so I'm tagging @fabiocav.

hanblee commented 6 years ago

FYI, as mentioned in #836, AWS Lambda allows one to target netcoreapp2.0 (https://aws.amazon.com/blogs/developer/aws-lambda-net-core-2-0-support-released/).

pscholtes commented 6 years ago

Hey @paulbatum, in https://github.com/Azure/Azure-Functions/issues/836#issuecomment-395919411 you mention that more "investigation" is required for this issue. I am just curious, but is this issue in active discovery/development on the MSFT side? Do you have any updates or roadmap for support? Thanks!

paulbatum commented 6 years ago

We're not spending cycles on this at the moment but we intend to in the coming months.

ghost commented 6 years ago

This issue is pretty much holding me from using Azure functions. Please spend cycles on this. Its keeping developers with existing .NET Core libraries on the WebJob side.

MisinformedDNA commented 6 years ago

Since this won't happen for a few months, at least, could your libraries target .NET Standard instead? If not, what is blocking that?

ghost commented 6 years ago

Its too much impact compared to the worth of the improvement. Im not suddenly targeting my production libraries to .NET standard. Its a fundamental change which requires full application testing and staging. Not something I put on my sprint that easy.

pscholtes commented 6 years ago

I'm seeing that with version 15.0.40617.0 of the AF extensions, you can pick either the v1 (.NET Framework) or the v2 (.NET Core) project template. When v2 is selected the resulting project still targets the .NET Standard framework.

In tracking this issue I recall that this is more or less how the extensions worked when v2 was introduced (i.e. choose v2 (.NET Core), but the project targets Standard); however, this confusion of Core/Standard was first discussed in #686 with @soninaren where ultimately it was changed to read v2 (.NET Standard) in 15.0.40502.0.

The 15.0.40617.0 release notes state that:

The tools will run v2 Azure Functions locally against .NET Core 2.1.

@paulbatum not trying to understate the nuances/complexities of this, but can you please provide any updates or insights related to the aforementioned changes?

paulbatum commented 6 years ago

Hi @pscholtes, unfortunately I dont have much else to add right now. The VS tooling has been built and tested to use class libraries that target .NET Standard, and there are technical problems that need to be worked through to allow you to work with class libraries that target .NET Core. We want to investigate but its not sitting at the top of our list of must-fix issues so I have no progress to report at the moment.

thierry-prost commented 6 years ago

The situation described by pscholtes's "real-life application" is exactly what our company is facing. It would mean the world if the issue could be prioritized. We've been looking at the github issues for months now with no real update on this.

sfmskywalker commented 6 years ago

I need Functions to target .NET Core as well.

In my case, I have a .NET Core class library that utilizes HttpClientFactory which today only exists in .NET Core. If I want to use Functions v2 and leverage this class library, it needs to target .NET Standard 2.0, which means managing HttpClient myself. Knowing all there is to know about HttpClientFactory, I really rather not :)

I wanted to look for a UserVoice idea on this, and turns out one does exist and is actually marked as "Completed"! But alas, although the title says "Support for NET Core", it was completed with support for NET Standard :(

MisinformedDNA commented 6 years ago

HttpClientFactory supports .NET Standard. See project file and NuGet. Hope this can unblock you for now.

Tealons commented 6 years ago

This also a blocker for us. Would be nice to get this fixed in the near future!

ghost commented 6 years ago

Please target .NET core so I can start using functions instead of workers. I have been waiting for months now. Thanks in advance!

MisinformedDNA commented 6 years ago

@keesdewit82 Why not use WebJobs? No one should have to use workers. ;) And conversions from WebJobs to Functions are more straightforward.

MisinformedDNA commented 6 years ago

@Tealons & @keesdewit82 Out of curiosity, what features of .NET Core are you using that prevents you from targeting .NET Standard?

ghost commented 6 years ago

@MisinformedDNA I have an existing .NET core solution. Changing my libraries to .NET standard would be a major change and would require full application testing. Too much for too little.

Btw, I meant WebJobs indeed, the one that runs in my App Service.

Tealons commented 6 years ago

@keesdewit82 @MisinformedDNA Exactly the same issue here with regard to the dependency.

ghost commented 6 years ago

I am about to start developing a .NET Core class library, that I would like to use with ASP.NET Core websites and Azure Functions. Unfortunately, this creates problems because Azure functions only run with .Net Standard. I want to use .NET Core for performance reasons (this is important to me): including Span, Memory and the forth coming linker. Today I have decided to go with .NET CORE, so Azure Functions are of little use to me. I was going to put a lot of functionality into Azure Functions. Now, all I will use them for are simple timers for checking web sites are running OK and processing a few Azure Storage Queues, such as a critical error queue. The code in these functions will have to be minimal. Six months ago, I would have said .NET Standard is the way to go. No longer, it is too dependent on other frameworks such as the .NET Framework and Xamarin. I read that the next release of the .NET Framework will not be implementing Span and Memory, so it will probably be a long time before they make it into .Net Standard. Azure functions really are useful, unfortunately, the teams developing the functionality only seem to be interested in one small .NET library. They need to be able to run with all the .Net Frameworks. Microsoft needs to sort this mess out.

Tealons commented 6 years ago

@Securso We decided to not use Azure function, but to create an implementation with IHostedServices. Maybe that's also a good alternative for you...

MisinformedDNA commented 6 years ago

@Securso The System.Memory package has the Span types for the .NET Framework, .NET Core and .NET Standard.

ghost commented 6 years ago

I will be doing a fair bit of text parsing in my application. Suppose I wish to parse at integer at offset 10 for a length of 3, in a string. With .Net Core 2.1, I simply create a span for the characters and call the relevant Int parse method. The parse is done without a copy of the sub string being placed on the managed heap. The managed heap is not used. As far as I’m aware, the other frameworks do not have the overload. If I used these, I would need to create a substring on the managed heap, and then parse that string, which is much slower. Hence the need to use .Net Core 2.1.

MisinformedDNA commented 6 years ago

Yup, I know exactly what you are talking about and those types were added to the System.Memory package for .NET Framework 4.5+ and .NET Core 2.0. It was Core 2.1 at first, but now you can use them anywhere. They've also made changes to RyuJIT to increase performance for all frameworks.

paulbatum commented 6 years ago

@MisinformedDNA The new types were added in the package you are referring to but not the overloads on existing types, such as the one that @Securso mentioned (int.Parse)

MisinformedDNA commented 5 years ago

@paulbatum I'm confused about the recent GA announcement of v2 with regard to this issue. It says

.NET developers can now author functions using .NET Core 2.1.

Some of the documentation also uses .NET Core verbage, like

Runtime 2.x runs on .NET Core 2

Most of the considerations required in moving between versions are related to the language runtime changes listed above (for example C# moving from .NET Framework 4.7 to .NET Core 2).

In fact, the only place I see .NET Standard referenced, is when the documentation calls out the target framework, all other places I've found reference .NET Core.

So can we target .NET Core now or not?

paulbatum commented 5 years ago

I agree that the first quote you pulled is a little bit misleading. Right now the VS tooling makes it easy to run on .NET core 2.1 but "using" implies a little more (such as being able to use APIs that only exist in .NET Core 2.1).

I think there is no issue with the second quote you pulled though. When you write a V2 function its running on .NET Core 2.1.

paulbatum commented 5 years ago

Hi folks, apologies that we had to delay this work item while we focused on V2 GA. The good news is that we'll be starting work on this next month. We expect to have manual steps that you can try by mid October, and our goal is to have all relevant template/tooling updates complete and deployed by the end of October.

Tracking work items:

fabiocav commented 5 years ago

The Microsoft.NET.Sdk.Functions package 1.0.23 was just published to Nuget. That version has the tooling changes to enable targeting netcoreapp2.1

Templates have not yet been updated, but to validate the new behavior, you can simply update the TargetFramework project property to netcoreapp2.1

Please let us know if you run into issues with that flow (also let us know if it works for you, as it would be good to get validation :) )

brandonh-msft commented 5 years ago

is it valid to be targeting core for something like a function app which is compiled as a DLL?? My understanding's always been if the code has an entry point it should target Core (vs Standard) whereas libs (aka DLLs) should be built on Standard.

shibayan commented 5 years ago

@fabiocav TargetFramework is changed to netcoreapp2.1 and debugging in Visual Studio, the following error will be displayed and functions not start.

image

Running with func.exe will work. but it is always an error from Visual Studio.

fabiocav commented 5 years ago

@shibayan does a simple build work for you? If not, can you share a build log with any errors you may find?

@brandonh-msft targeting netcoreapp2.1 is valid, and that would give you a class library that can be consumed by other .NET Core apps. With that, you would have access to .NET Core APIs not in .NET Standard, also be able to consume other .NET Core dependencies, but as you can expect, that would sacrifice compatibility. This is equivalent to picking the .NET Core Class Library template in VS.

brandonh-msft commented 5 years ago

@fabiocav 👍 but I feel it's worth clarifying that the current .Net Standard DLL a Function App is built in to today would also be consumable by a .Net Core app

shibayan commented 5 years ago

@fabiocav Yes. I just created Azure Function v2 and HttpTrigger using template in Visual Studio and changed TargetFramework to netcoreapp2.1. It seems to be a Visual Studio error, but I could not find the log.

brandonh-msft commented 5 years ago

@pscholtes I'm curious. Can you give me more detail on why you centralized your logic in to a .Net Core library instead of a .Net Standard one?

paulbatum commented 5 years ago

@brandonh-msft Most of the customers that I've talked to about this are targeting .NET Core because of the additional APIs that don't exist in .NET Standard.

fabiocav commented 5 years ago

Yeah, I was able to repro that.

While we investigate, can you change your project properties from project to executable for the launch option under Debug and use the following executable path: %localappdata%\AzureFunctionsTools\Releases\2.8.1\cli\func.exe and add host start to the arguments.

shibayan commented 5 years ago

Thanks! I can now be debugging from Visual Studio.

pscholtes commented 5 years ago

Hey @brandonh-msft! I believe at the time of this issue the latest .NET Standard version was missing critical API support for my application (maaaybe EFCore?). I honestly don't have a ton of working knowledge or experience with .NET Standard, so I likely didn't explore that avenue. I think I had incorrectly assumed that Standard would eventually go away and everything would be Core... but it's looking like we'll have both options for the foreseeable future?

I got the same "fatal error" prompt from VS2017 and the fix described by @fabiocav did the trick (though it's %LocalAppData% for those following along at home).

fabiocav commented 5 years ago

@pscholtes thanks for the update! I've corrected the typo above! :)

brandonh-msft commented 5 years ago

@pscholtes fair enough, though even EFCore only takes .NetStandard as a dependency image

I fully empathize w/ the confusion between Core and Standard so I'm trying to understand if it's a messaging/education issue or if there's a legit reason to create a library based on Core that I'm missing. This said, I did some research and did find a list of the missing namespaces from Standard that are present in Core and was a bit surprised at what I found (System.Buffers, for instance) but you're always free to bring those libs in separately (as EFCore does with System.Collections.Immutable (missing from Standard, present in Core), for example).

fabiocav commented 5 years ago

In addition to .NET APIs, we also have customers who wanted to use dependencies they were bringing in that only supported .NET Core, and investing in changing the target for those dependencies was impractical or impossible (e.g. they didn't own the dependency). This change unblocks those customers in Functions.

pscholtes commented 5 years ago

@brandonh-msft it's mostly messaging/education for me... when I see ".NET Standard" my brain interprets that as something akin to like .NET CF on a Pocket PC.

gladitormaximus commented 5 years ago

Some of the discussion in this issue is relevant - it provides steps that can get a function app with target netcoreapp2.0 compiling, but not running: Azure/azure-functions-vs-build-sdk#160 (comment)

This is the error you'll get if you try this: image

It would be good to understand whether we expect to be able to get this working. I don't understand the details so I'm tagging @fabiocav.

Just an update on how I fixed this run time error - [Updated Azure Functions Web Jobs Tools from 15.8 to 15.10].

colbroth commented 5 years ago

Some of the discussion in this issue is relevant - it provides steps that can get a function app with target netcoreapp2.0 compiling, but not running: Azure/azure-functions-vs-build-sdk#160 (comment) This is the error you'll get if you try this: image It would be good to understand whether we expect to be able to get this working. I don't understand the details so I'm tagging @fabiocav.

Just an update on how I fixed this run time error - [Updated Azure Functions Web Jobs Tools from 15.8 to 15.10].

An update to Azure Functions and Web Job Tools version 15.10.2046.0 fixed this error for me. I was at a previous version of 15.10 and still received the error.

paulbatum commented 5 years ago

Folks, we released the tooling updates last week. The default experience for File -> New Project -> Azure Functions is now a .NET Core 2.1 class library.

image

image

If you get the error in the screenshot in the post from @colbroth above, make sure you update to the latest version of the Azure Functions and Web Jobs Tools.

Anyone tried it out? I'd like to close this issue but I was hoping to hear from a few of you on how well this is working before I do that :)

paulbatum commented 5 years ago

Also I should note that while I was talking about and screenshotting VS, all of this is true for Visual Studio Code as well :)

oluatte commented 5 years ago

@paulbatum I just tried this but i immediately ran into issues getting the Startup class into the extensions.json file. The known workarounds (build target etc.) don't work with .netcore 2.1

fabiocav commented 5 years ago

@mayoatbm can you open a separate issue with the details of your problem (your startup setup, details on which assembly you're applying the attribute to, etc.?)

oluatte commented 5 years ago

@fabiocav Done. Thanks.

MisinformedDNA commented 5 years ago

@paulbatum

When I tried creating a new project via "Recent project templates" on the "Start page", I'm pretty sure I saw ".NET Standard". But when I clicked on "Create new project" and selected "Azure Functions" from the dialog, it said ".NET Core". I checked "Recent project templates" again and it now says ".NET Core". So either I read it wrong the first time, or there was some caching involved.

On 15.10.2046.0