Using Azure Functions from another project - .net-core

I am trying to make a base/abstract class that contains an Azure Function, which I can use from within a different project when it inherits from the base, but can't seem to get the functions from within the base class of the first project to appear.
(Currently using Azure Functions v3 in .Net Core 3.1 in VS2019)
Here's what I have tried...
Base class in project 1:
public class BaseClass
{
[FunctionName("Function1")]
public IActionResult Function1(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req,
ILogger log)
{
// Function 1 code in here
}
}
New class in project 2:
public class NewClass : BaseClass
{
[FunctionName("Function2")]
public IActionResult Function2(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req,
ILogger log)
{
// Function 2 code in here
}
}
So, when I run project 2 locally, I thought I should get Function1 and Function2 endpoints ready to be used, but I only get the endpoint for Function2 that is available.
If I run project 1 locally, I get the endpoint for Function 1.
Is this even possible in Azure Functions and, if so, how do I achieve this?
UPDATE - If I move the BaseClass from project 1 into project 2, I get what I want, namely Function 1 and Function 2 at the same time.
UPDATE 2 Repro steps:
Create project 1: Create a new Azure Functions v3 targeting .Net 3.1.
Add an Azure Function using an HTTP trigger.
Run the project. (Basic/demo function 1 should run as expected.)
Create project 2: add another new project in the same solution: Azure Functions v3 targeting .Net 3.1.
Add an Azure Function using an HTTP trigger (to the new project).
Run the new project. (Basic/demo function 2 should run as expected.)
Add a project reference from Project 2 to Project 1.
Make Project 2's class inherit from Project 1's class.
Change each function in each project to NOT be a static class (to allow inheritance to work)
Run Project 2 - only Project 2's functions are displayed.
...then...
Move the Function1.cs file from Project 1 into Project 2 and rename classes/namespaces appropriately and then run the project... both functions are displayed.

One of the work arounds is to call the objects of Base Class in your Derived class i.e..
If your Solution looks like this
Solution
│ Base Project
└───────BaseFunction.cs
│ Derived Project
└───────DerivedFunction.cs
in your DerivedFunction.cs you can use DerivedProject.DerivedFunction.Run()
but the whole point of using Azure functions is to have multiple functions in a single project that will all be deployed at the same time. So, whatever you are doing is expectable (i.e.. Adding The function from Project2 to project1 and using inheritance).
If you are trying to debug both the functions at the same time then you can Add Other Project and using the reference to the existing project but using different ports.
REFERENCES:
Multiple Azure App Function in a project
Multiple function projects using different ports

I think what you are looking is the <FunctionsInDependencies>true</FunctionsInDependencies> property.
More info:
https://stackoverflow.com/a/62800977/6593791
https://www.ericksegaar.com/2021/01/19/discover-precompiled-function-apps/

Related

AmbiguousMatchException: The request matched multiple endpoints

I am using the Ardalis Clean Architecture for one of my projects. I am getting the above-mentioned error if I have the same action method (for example: Edit) in more than one controller and I try to call that method from anywhere. But if I add the following line in the controller just above where you declare public class and the controller name then the error disappear.
[Route("[controller]/[action]")]
I don't face the same issue in a normal asp.net core 6.0 project so I guess there is something in the Ardalis Clean Architecture template that is causing this.

EF Core in .NET Core library

The main idea is to add a EF Core nuget package to a .NET Core library project and then use that library in a bunch of applications (e.g., ASP.NET Core, Win Service, Console App) without configuring EF in each of them. And, if possible, without adding EF packages to each of them.
I'm wondering if it's possible.
My current problem is that I can't create a database based on the model I have in the library project.
It seems I can't just select the library project in the Package Manager Console and run update-database. It wants me to implement 'IDesignTimeDbContextFactory'.
I'm using .NET Core 2.1. Would it help if I update it to the latest version?
As mentioned by the error, you need to implement IDesignTimeDbContextFactory which is part of the Microsoft.EntityFrameworkCore.Design package so go ahead and install that in your library. Then create a class that implements IDesignTimeDbContextFactory appropriately.
Since you created a .NET Core library, set that as your startup project.
Then in your Package Manager Console, select your library as the Default project and run update-database.
Yes, you can do this.
Make sure you have all the prerequisites installed.
Create a .NET Core Console app
Create a Core Class library for Entity Framework
Reference the Class library from the Console App
Scaffold your database, go to Tools > Package Manager Console
From the dropdown set your default project to your class library so it will scaffold there.
Run this in the console (database first approach): Scaffold-DbContext "Your connecting string here" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models/EF -f
Create a class to get your context
public class Context
{
// See all queries generated by EF in debug window
public static readonly LoggerFactory MyLoggerFactory
= new LoggerFactory(new[] { new DebugLoggerProvider((s, level) => level >= LogLevel.Trace) });
public static DF.Data.Models.EF.YourContext GetContext()
{
var optionsBuilder = new DbContextOptionsBuilder<DF.Data.Models.EF.YourContext>();
optionsBuilder.UseSqlServer(
"Your Connection String").UseLoggerFactory(MyLoggerFactory);
return new DF.Data.Models.EF.YourContext(optionsBuilder.Options);
}
public partial class YourContext : DbContext
{
public YourContext(DbContextOptions optionsBuilderOptions) : base(optionsBuilderOptions)
{
}
}
}
Create a Repository class to store your queries if you would like.
Note: When you scaffold the database again make sure you select the Class library project as the default project from the dropdown. Then set your other project back to the startup project.

How to get appsettings from project root to IDesignTimeDbContextFactory implementation in ASP.NET Core 2.0 and EF Core 2.0

I am building an application in ASP.NET Core 2.0 and I am having problems with EntityFramework Migrations.
I have my DbContext in a separate project (SolutionName\ProjectNamePrefix.Data) and therefore I created an implementation for the IDesignTimeDbContextFactory interface.
I wanted to use different connection strings for different environments and I need appsettings.json for that.
So after a quick search I found that I can create a new IConfigurationRoot object inside the CreateDbContext function as shown here:
https://codingblast.com/entityframework-core-idesigntimedbcontextfactory/
I added that and then for testing, tried to run dotnet ef migrations list -c MyContext from the Data project root folder.
Then I got the following error:
The configuration file 'appsettings.json' was not found and is not optional. The physical path is 'C:\dev\*SolutionName*\*ProjectNamePrefix*.Data\bin\Debug\netcoreapp2.0\appsettings.json'.
So, basically, I tried 3 options for getting the correct root path:
Directory.GetCurrentDirectory();
env.ContentRootPath; (IHostingEnvironment object, I found a way to get it here: https://github.com/aspnet/Home/issues/2194)
AppDomain.CurrentDomain.BaseDirectory;
and all of them returned the same ..\bin\debug\netcoreapp2.0\ path. When I run the Data project from VS, then the two first options give me the correct project root folder.
Is there a way to get the correct project content root folder?
Because when I added --verbose to the EF command, it logged out a row:
Using content root 'C:\dev\FitsMeIdentity\FitsMeIdentity.Data\'.
So I understand that EF somehow knows the project root but all the options mentioned above return the path for the already built application.
The only option I found that works is that I change Copy output to root folder to Copy always but found from here: https://www.benday.com/2017/02/17/ef-core-migrations-without-hard-coding-a-connection-string-using-idbcontextfactory/ that it's not a good idea.
At first I even thought about creating a Constructor for the IDesignTimeDbContextFactory implementation which gets IOptions as a parameter but that didn't work, had the same problem as explained here:
Injecting Env Conn String into .NET Core 2.0 w/EF Core DbContext in different class lib than Startup prj & implementing IDesignTimeDbContextFactory
A little late, but here is the solution for those who hate hard-coding connections strings:
internal class MigrationDbContextFactory : IDesignTimeDbContextFactory<AppDbContext>
{
public AppDbContext CreateDbContext(string[] args)
{
IConfigurationRoot configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", false)
.Build();
string connectionString = configuration.GetConnectionString("DefaultConnection");
DbContextOptionsBuilder<AppDbContext> optionsBuilder = new DbContextOptionsBuilder<AppDbContext>();
optionsBuilder.UseMySql(connectionString,
ServerVersion.AutoDetect(connectionString),
mySqlOptions =>
mySqlOptions.EnableRetryOnFailure(
maxRetryCount: 10,
maxRetryDelay: TimeSpan.FromSeconds(30),
errorNumbersToAdd: null));
return new AppDbContext(optionsBuilder.Options);
}
}
No. You can't do this, and more to the point: you're not supposed to do this. The whole entire point of IDesignTimeDbContextFactory is that it's a way to get a DbContext instance from in a context where there is no ASP.NET Core framework to work with, i.e. from a class library. If you're running migrations from an ASP.NET Core project, you don't need it, and if you're not, none of the configuration stuff is available.
Additionally, it's only to be used for development, hence the "DesignTime" part of the name. As a result, there's no need for stuff like switching between connection strings for different environments. Just hard-code the connection string as the docs detail.

Attempted to call method "share" on class "Silex\Application" in Silex 2

I am developing a project with silex-skeleton in its most recent version. When trying to use the share method shows me the following error:
Code:
$app['login'] = $app->share(function() use($app) {
return new Model\UserModel($app);
});
Error:
Attempted to call method "share" on class "Silex\Application"
Any suggestions or possible cause of this failure
Silex 2.0 is using Pimple 3.0 which has removed the shared method, now all services are shared by default, if you want a new instance you must call the factory method as stated in the changelog for version 2.0.
So if you want a login service you should create it like this:
<?php
$app['login'] = function($app) {
return new Model\UserModel($app);
};
You can take a look at the docs for the 3.0 Pimple version directly on it's GitHub repository
PS: Keep in mind that, at the time of this writing, Silex 2.0 is in development, so be prepared to adapt your code until it gets a 2.0 stable version. 2.0 has reached prod status as of 2016-05-18

How to access namespace which is part of different project?

I have two C#.net projects project 1 and project 2 (names changed) in single solution. I am using Visual Studio 2005. I have added reference of project 2 in project 1 by right clicking and choosing 'Add Reference'. Both projects are of 'Application' project type not Class library type. I have some classes in project 2 which I want to access in project 1. After adding reference I tried to use import namespace of project 2 in project 1 but I guess its not available. Visual studio Intelisense is not showing me the desired namespace.
Can anyone please suggest about how to access namespace and classes across multiple projects?
EDIT :- Is it because there are different assemblies for both the projects?
Thanks
Make sure the classes you want to access are public. So suppose you have the following class in Project 2:
namespace Project2
{
public class Foo { }
}
In Project 1 after you've referenced Project 2 you can use this class:
namespace Project1
{
using Project2;
public class Bar
{
public Bar()
{
Foo foo = new Foo();
}
}
}
Import is a Visual Basic.NET term. In C# you would use using.

Resources