So I'm aware of these two questions that seem to be asking the same thing:
How to remove the word ‘api’ from Azure functions url
How to change the base "/api" path on Azure Functions (v2)?
However, I can still not get rid of the "api" prefix in my route.
My host.json looks like:
{
"version": "2.0",
"extensions": {
"http": {
"routePrefix": ""
}
}
}
And on my HttpTrigger I'm setting my custom route:
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "myapp")] HttpRequest request,
However, when I run the app locally the end point is coming up as:
[POST] http://localhost:7071/api/myapp
If I change my host.json to:
{
"version": "2.0",
"extensions": {
"http": {
"routePrefix": "something"
}
}
}
My app is now running on:
[POST] http://localhost:7071/something/myapp
So it appears that giving an empty string "" is just not working. Any ideas? (I've done all the usual stuff: clean solution, delete bin/obj folder etc.)
FYI from my function app I'm using:
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.7" />
EDIT:
I'm also referencing these packages from the function app (though I don't see how this would cause this problem):
<PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="3.1.1" />
EDIT 2
I've narrowed down the problem to this code that is called in Startup.cs:
IConfiguration configuration = builder.Services.BuildServiceProvider().GetService<IConfiguration>();
IConfiguration combinedConfig = new ConfigurationBuilder()
.AddConfiguration(configuration)
.AddAzureKeyVault(kvEndpoint, kvClient, new DefaultKeyVaultSecretManager());
.Build();
builder.Services.AddSingleton(combinedConfig);
// <-- this line causes the prefix "" to revert to "/api"
It essentially is adding key vault as a configuration provider to the stack of providers all ready there. (Note it doesnt matter what .Add methods I call on configuration builder, its the registration that is causing a problem). Is there another way to write this maybe?
So the mistake I seem to have made was very small. In the following code:
IConfiguration configuration = builder.Services.BuildServiceProvider().GetService<IConfiguration>();
IConfiguration combinedConfig = new ConfigurationBuilder()
.AddConfiguration(configuration)
.AddAzureKeyVault(kvEndpoint, kvClient, new DefaultKeyVaultSecretManager());
.Build();
builder.Services.AddSingleton(combinedConfig);
ConfigurationBuild.Build() actually returns a IConfigurationRoot, NOT a IConfiguration (IConfigurationRoot is a superset of IConfiguration). So when registering it I was loosing something (probably config provider information).
Simply changing:
IConfiguration combinedConfig
to
IConfigurationRoot combinedConfig
fixes the problem (or you can use var, which I probably should have!).
Though this fixes the problem I am still a little confused why before changing the routePrefix in host.json to some non-empty string works but setting it to empty string does not. Would have thought simply having the setting in the host.json at all would just apply the value and not having it there would mean reverting to the default "api".
I tried, and it's working!
I used VS2019, Created Azure function default project with HTTP trigger and remove route prefix from host.json
Proj file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<AzureFunctionsVersion>v2</AzureFunctionsVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="1.0.31" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
</Project>
After updating nuget packages with latest version, it's working.
Proj file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<AzureFunctionsVersion>v2</AzureFunctionsVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
<PackageReference Include="Microsoft.Azure.WebJobs.Core" Version="3.0.16" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Http" Version="3.0.2" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.7" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
</Project>
Related
I have an Azure function(V3) that uses BlobTrigger binding and written in C#.
In order to add custom properties in Application Insights RequestTelemetry for it using
Activity.Current?.AddTag("TraceId", traceId);
I need to access the Activity.Current based on the suggestion from this Stackoverflow answer. However, it didn't work due to Activity.Current is NULL.
My package configuration looks like as follow:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AzureFunctionsVersion>v3</AzureFunctionsVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Azure.Storage.Blobs" Version="12.9.0" />
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.14.0" />
<PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="5.0.0-beta.2" />
<PackageReference Include="Microsoft.Azure.WebJobs.Logging.ApplicationInsights" Version="3.0.14" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.8" />
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.3" />
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="5.0.1" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
</Project>
And my function looks like as follow:
[FunctionName("Create-Thumbnail")]
public async Task CreateThumbnail([BlobTrigger("input/{name}", Source = BlobTriggerSource.EventGrid, Connection = "AzureWebJobsStorage")] Stream image,
IDictionary<string,string> metadata,
string name,
ILogger log,
ExecutionContext context)
{
Activity.Current?.AddTag("TraceId", traceId);
}
I have been doing research for whole day but failed to find any solution. Does anyone know what could be the issue?
Currently it can be working in HTTP Trigger Functions that were ending up in the Custom Properties of Requests in application insights are no longer. Refer here
The same Activity.Current value is null issue available in github Azure Function host & Application Insights
The Application Insights .NET SDK uses DiagnosticSource (DiagnosticSourceUsersGuide) and Activity (ActivityUserGuide) steps to collect and correlate telemetry.
Please open an issue in the Functions repo link here.
Thanks to this GitHub issue, I manage to get it work after downgrading System.Diagnostics.DiagnosticSource to to version 4.6
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="4.6.0" />
we are trying to invoke azure cognitive services- translator api using azure function apps.We are getting the following error in the c# terminal:
No job functions found. Try making your job classes and methods
public. If you're using binding extensions (e.g. Azure Storage,
ServiceBus, Timers, etc.) make sure you've called the registration
method for the extension(s) in your startup code (e.g.
builder.AddAzureStorage(), builder.AddServiceBus(),
builder.AddTimers(), etc.).
Our C# code for reference:
private const string key=" ";
private static readonly HttpClient client=new HttpClient
{
DefaultRequestHeaders={{"Ocp-Apim-Subscription-key",key}}
};
public static async Task Main()
{
while(true){
var text=Console.ReadLine();
var translatedText=await Translate(text,"en");
Console.WriteLine(translatedText);
}
}
public static async Task<string> Translate(string text,string language){
var encodedText=WebUtility.UrlEncode(text);
var uri="https://api.microsofttranslator.com/V2/Http.svc/Translate?" + $"to={language}&text={encodedText}";
var result=await client.GetStringAsync(uri);
return XElement.Parse(result).Value;
}
Also .csproj file code for reference:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AzureFunctionsVersion>v3</AzureFunctionsVersion>
<RootNamespace>transaltor_cognetive_service</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.7" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.7" >
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
<PropertyGroup>
<LangVersion>7.1</LangVersion>
</PropertyGroup>
</Project>
As an addition to the MarleneHE's comment:
You're missing a FunctionNameAttribute and a TriggerAttribute. Without those, the Functions Runtime doesn't know which of the methods is the entry point, or how to trigger it.
In a class library, a function is a static method with a FunctionName and a trigger attribute
and
The FunctionName attribute marks the method as a function entry point. The name must be unique within a project, start with a letter and only contain letters, numbers, _, and -, up to 127 characters in length. Project templates often create a method named Run, but the method name can be any valid C# method name.
The trigger attribute specifies the trigger type and binds input data to a method parameter.
I am trying to use
wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementIsVisible(By.Id("logonIdentifier")));
However I am getting an error Could not load file or assembly 'SeleniumExtras.WaitHelpers. I am using
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DotNetSeleniumExtras.WaitHelpers" Version="3.11.0" />
<PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="TestProject.SDK" Version="0.63.1" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<IsPackable>false</IsPackable>
<PublishChromeDriver>true</PublishChromeDriver>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DotNetSeleniumExtras.WaitHelpers" Version="3.11.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.1.0" />
<PackageReference Include="MSTest.TestFramework" Version="2.1.0" />
<PackageReference Include="coverlet.collector" Version="1.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\testForLogin\testForLogin.csproj" />
</ItemGroup>
</Project>
It works locally but when I tried pushing it to the testproject.io I get the above error message.
I am not able to change it to the recommend selenium web driver version.
The package you are using is not .NET Core compliant. With some restructure of the code what you need is available with
using OpenQA.Selenium.Support.UI;
Then take the code that used the SeleniumExtras wait helpers and change to use methods on your driver class such as
WebDriverWait browserWait = new WebDriverWait(driver, TimeSpan.FromSeconds(90));
browserWait.Until(driver => driver.FindElement(By.Id("logonIdentifier")).Displayed);
You could easily check the properties on the driver as well, say for the Url, such as
const string expectedUrl = "https://www.google.com";
browserWait.Until(driver => driver.Url == expectedUrl);
Then go remove the package you are no longer using from your project
dotnet remove package DotNetSeleniumExtras.WaitHelpers
Which funny enough is pretty much the homepage of https://www.selenium.dev/documentation/en/ but when you search you tend to get distracted by the SeleniumExtras project.
On Startup.cs in my Azure Function v2 project:
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using MyCompany.MyLib.Contracts; //namespace from external library
[assembly: FunctionsStartup(typeof(Startup))]
namespace Test
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddTransient(typeof(Logging.ILogger<>), typeof(Logging.Logger<>));
builder.Services.AddTransient<IUserLogic, UserLogic>();
builder.Services.AddTransient<IBillingLogic, BillingLogic>(); //---> loads up from above referenced "MyCompany.MyLib.Contracts" namespace and this namespace is from externally referenced class library but with in same solution
}
}
}
The above code with my own custom classes within function app project like "EmailLogic", "Logger" works fine.
But the moment I added up custom classes to services container like "BillingLogic" from external C# library project which is added as reference project from the existing visual studio solution it throws up below issue:
"A host error has occurred during startup operation '945918c0-af3a-4d50-ab1d-ac405d4f1c7b'. [2/3/2020 2:11:02 PM] MyFunction.FunctionApp: Could not load file or assembly 'MyCompany.MyLib.Contracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Could not find or load a specific file. (Exception from HRESULT: 0x80131621). System.Private.CoreLib: Could not load file or assembly ''MyCompany.MyLib.Contracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
If these lines from "referenced external projects" are removed,
using MyCompany.MyLib.Contracts;
builder.Services.AddTransient<IBillingLogic, BillingLogic>();
startup.cs works as expected but referring this external class from referenced project is must for my solution.
My Azure function csproj file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AzureFunctionsVersion>v2</AzureFunctionsVersion>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<AutoGenerateBindingRedirects>false</AutoGenerateBindingRedirects>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.0.0" />
<PackageReference Include="Microsoft.Azure.Storage.Queue" Version="11.1.2" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="3.0.8" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.2.0" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="1.0.29" />
<PackageReference Include="NLog" Version="4.6.8" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="NLog.Extensions.AzureStorage" Version="1.1.4" />
<PackageReference Include="Microsoft.Azure.DocumentDB.Core" Version="2.9.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MyCSharpLib.DataStore\MyCSharpLib.DataStore.csproj">
<Private>true</Private>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
</None>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
<None Update="nlog.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
</None>
</ItemGroup>
</Project>
MyCSharpLib.DataStore.csproj file:
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RuntimeIdentifier>win7-x64</RuntimeIdentifier>
<Platforms>x64</Platforms>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<ItemGroup>
<PackageReference Include="Microsoft.Azure.Cosmos.Table" Version="1.0.6" />
<PackageReference Include="Microsoft.Azure.DocumentDB.Core" Version="2.9.2" />
<PackageReference Include="Microsoft.Azure.Storage.Blob" Version="11.1.1" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Newtonsoft.Json.Bson" Version="1.0.1" />
<PackageReference Include="Polly" Version="5.3.1" />
<PackageReference Include="StackExchange.Redis" Version="1.2.6" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MyContractLib.Contracts\MyContractLib.Contracts.csproj" />
</ItemGroup>
</Project>
MyCSharpLib.DataStore
.\MyContractLib.Contracts\MyContractLib.Contracts.csproj
My Azure function csproj file:
<ProjectReference Include="..\MyCSharpLib.DataStore\MyCSharpLib.DataStore.csproj">
so
using MyCompany.MyLib.Contracts;
is coming through the ref to DataStore which then has ref to MyContractLib.Contracts
But it is not coping the dll as its silly, so either get Azure function csproj to ref MyLib.Contracts
or do this
How to set dependencies when I use .NET Standard 2.0 DLL libraries with a .NET Framework console application?
which is on all your std libs add
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
so on both your standard libs
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>
if this does not work i will delete
I am creating ASP.NET Core web application and hosting it via console.
I am using IdentitySvr4 Quick Start UI and getting all the files to my project.
Now when I start the server by running console and browse to http://localhost:44322/, I am getting error,
InvalidOperationException: The view 'Index' was not found. The following
locations were searched:
/Views/Home/Index.cshtml
/Views/Shared/Index.cshtml
/Pages/Shared/Index.cshtml
I have created this project as console application and added all the nugets along the way.
The webserver starts and listens on the port, but somehow the view engine does not understand.
Main Program:
class Program
{
static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args).UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseUrls("http://*:44322")
.UseStartup<Startup>();
}
Startup class:
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
var signingCertificate = new X509Certificate2(Helpers.GetCertificate());
services.AddIdentityServer()
.AddSigningCredential(new X509Certificate2(signingCertificate))
.AddTestUsers(InMemoryConfiguration.Users().ToList())
.AddInMemoryClients(InMemoryConfiguration.Clients().ToList())
.AddInMemoryApiResources(InMemoryConfiguration.ApiResources());
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole();
app.UseDeveloperExceptionPage();
app.UseIdentityServer();
app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
}
}
Normally I would not answer my question, and just add a comment , but I think this will save the devs a lot of effort and pain.
It was simple,
I edited the .csproj with Notepad++ and found following settings:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="IdentityServer4" Version="2.3.2" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />
</ItemGroup>
</Project>
After refering to a webproj, just changed it to a webproj by changing the root from "Microsoft.NET.Sdk" , to "Microsoft.NET.Sdk.Web"
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="IdentityServer4" Version="2.3.2" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />
</ItemGroup>
</Project>
And tha's it. Not sure why all the application logic will depend on the project type (since it could be hosted any where), but works like a charm.
For me, the error was within my .csproj file. The ItemGroup content was excluding Index.cshtml. I removed this reference and now I can navigate to Index.cshtml.
<pre><code>
<ItemGroup>
<Content Remove="Views\Employee\Delete.cshtml" />
<Content Remove="Views\Employee\Index.cshtml" />
</ItemGroup>
</code></pre>
I edited the .csproj
Just remove this (if is Exist)
"<RazorCompileOnBuild>false</RazorCompileOnBuild>"
"<RazorCompileOnPublish>false</RazorCompileOnPublish>"
from <PropertyGroup>
By default the "RazorCompileOnBuild" & "RazorCompileOnPublish" not found in <PropertyGroup>
dotnet clean
fixed it for me (.NETCore 6)