Deploy .netcore to iis - iis

I have a .net core app and runs fine on kestrel server.
http://localhost:5000/mapapi/v1.0/branch
I have deployed the app to IIS using publish tool in visual studio 2017 and with in program.cs, I have this line of code
.UseIISIntegration()
when I run the app I get an error
An error occurred while starting the application.
Exception: Cannot read variable
It is not reading the variable from launchsettings.json. I also created a profile by the name "IIS"
"IIS": {
"commandName": "iis",
"launchBrowser": true,
"launchUrl": "mapapi/v1.0/Branch",
"environmentVariables": {
"ConnectionString": "myhiddenconnectionstring",
}
}
What am I doing wrong? what other places do I have to look and make sure the application reads the values appropriately. Anyone in the community who had experience .net core to IIS, please share you knowledge with the community. We would appreciate it.

Related

Updating databases in Entity Framework for development and production environments in ASP.NET Core

How do I apply EF migrations to multiple databases, referencing either a Development or Production environment as required?
TL;DR
I'm developing an ASP.NET Core MVC application using Entity Framework that references different databases for Development and Production. Both databases are hosted Azure SQL databases.
The application at the moment is running on IIS Express on my Development machine, but I will deploy Production to an Azure App Service. I'm using Entity Framework and migrations to update the database design.
I've applied this answer to use a different database connection string for either the Development or Production launch configurations, and this seems to be working. The connection strings are then stored in appsettings.Development.json or appsettings.Production.json.
When I select the DEV launch configuration, I am able to use the EF cli command dotnet ef database update in order to apply my migrations to the development database. Works fine.
However, I cannot work out how to tell Visual Studio to apply each migration to the production database when I run under the PROD launch configuration.
Running the command dotnet ef database update after changing the launch configuration continues referencing the development database, and nothing changes. I'm not surprised by this - I haven't told Visual Studio where to find the other database. But I also can't work out how to do this.
Is there a way to change the referenced database, based on the launch configuration or environment variables? Or some other convenient way?
launchSettings.json
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:57961",
"sslPort": 44320
}
},
"profiles": {
"IIS Express (dev)": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express (prod)": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Production"
}
}
}
}
According to the documentation, you can specify the connection string as an extra parameter:
--connection: The connection string to the database. Defaults to the one specified in AddDbContext or OnConfiguring.
So this command will let you specify which database you are targeting:
dotnet ef database update --connection "<sql connection string>"

.NET 5 webapi example returning 404, running in Linux

I'm trying to use .NET 5.0 on Linux, using VS Code.
I've created an empty directory, ran "code ." in it to open it up in VS Code, then created the sample project with:
dotnet new webapi -n Experimenting
When the "Required assets to build and debug are missing from 'experiments'. Add them?" dialog appeared, I clicked "Yes".
I ran the build task, then selected "Start Debugging" from the "Run" menu.
The project appears to run, and it opened up a Chrome browser tab to https://localhost:5001/, and the tab displays HTTP ERROR 404.
The "Expementing" profile in lauchSettings.json has applicationUrl set to "https://localhost:5001;http://localhost:5000", and the debug console includes:
Now listening on: https://localhost:5001
Now listening on: http://localhost:5000
So the ports seem to be correct.
If I try to open a browser tab on http://localhost:5000, it redirects to https://localhost:5001, and then shows the 404.
What am I missing?
The comment by jmoerdyk is correct - if I try https://localhost:5001/swagger, I get the swagger page.
In .NET Framework, Web API creates a landing page at the domain root. .NET Core does not.
The question, then, is why is the browser tab opening up at https://localhost:5001, and not at https://localhost:5001/swagger?
I had noticed this in launchSettings.json:
"profiles": {
"IIS Express": {
...
},
"Experimenting": {
"commandName": "Project",
"dotnetRunMessages": "true",
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
And I thought that should open up the browser pointing to the swagger page. Browsing around I've seen statements that that launchSettings.json is not used by VS Code, but it clearly is, because if I change ports in applicationUrl, I the swagger page running on the new ports.
But launchUrl seems to be ignored.
Browsing around the web gives me the same sort of wrong and outdated answers that is typical for .NET Core questions, but I eventually tried setting the uriFormat in launch.json:
{
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (web)",
...
// Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
"serverReadyAction": {
"action": "openExternally",
"pattern": "\\bNow listening on:\\s+(https?://\\S+)",
"uriFormat": "%s/swagger"
},
...
},
]
}
The link in the comment explains how this is supposed to work - kinda.
https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
The reason for 404 code that there is no defautl GET request for root as you figured out already.
Based on this record, it tells that launchSettings.json is only for Visual Studio debug. I tried project on Windows with VS and on Linux with dotnet CLI, I can confirm this experience.
Is launchSettings.json used when running ASP.NET 5 apps from the command line on Mac?
You can use a redirect as alternative way for route to get Swagger as default instead of launchSettings.json file. You can create this class (for example as RouteRedirectController.cs) onto Controllers folder and it will redirect to swagger in case of a root GET call:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace TestAPI.Controllers
{
[ApiController]
[Route("")]
public class RouteRedirectController : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return Redirect("~/swagger");
}
}
}
Update: To be honest, it is a bit strange because if I change "applicationUrl" in launchSettings.json file (not for IIS Express profile that is for Windows), then change is reflected after dotnet run command is executed. Ignore launchUrl maybe a bug during dotnet run? But if it does anyway, then it can be resolved by this redirect endpoint.

Trouble Configuring Tracing Application Insights in ASP.NET Core 2.0 Razor Pages

I created a new ASP.NET Core 2.0 web application in Visual Studio 2017 which results in a Razor Pages implementation.
In my Index.cshtml.cs file, I implemented this:
public void OnGet()
{
Trace.TraceError("*************** INDEX ERROR ***************");
Trace.TraceWarning("*************** INDEX WARNING ***************");
Trace.TraceInformation("*************** INDEX INFORMATION ***************");
Trace.WriteLine("*************** INDEX WRITELINE ***************");
var telemetry = new Microsoft.ApplicationInsights.TelemetryClient();
telemetry.TrackTrace("*************** INDEX TRACKTRACE ***************");
}
I did all of the configuration to my Application Insights instance.
appsettings.json
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Trace"
}
},
appsettings.Development.json
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Trace",
"System": "Information",
"Microsoft": "Information"
}
}
When I run my page and watch the Log streams page, I can see the telemetry.TrackTrace entries, but not the Trace.Trace* entries.
What am I missing?
If you are using Application Insights SDK for Asp.Net Core, it can collect only traces sent using ILogger mechanism. Please follow instructions here if you are headed this route:
https://github.com/Microsoft/ApplicationInsights-aspnetcore/wiki/Logging
But it seems like you are logging using System.Diagnostics.Trace methods. Application Insights can capture these, but it require installation of additional nuget (https://www.nuget.org/packages/Microsoft.ApplicationInsights.TraceListener/2.6.0-beta3), the latest beta of which support .net core apps.

Events not flowing to Application Insights when using secrets.json in localhost

I used this Application Insights getting started guide for setting up my application. I'm running VS2017 version 15.5.7 and my application is using AspNetCore 2.0.0.
When I F5 debug my application using IIS Express from Visual Studio, I see Application Insights events within the debugger Events window. However, the same events are not flowing to Application Insights in Azure; I've configured the InstrumentationKey within secrets.json as you can see below. I've confirmed the key is loaded into my application configuration by setting a breakpoint.
As another debugging data point, I've confirmed events do successfully flow to Application Insights when running in a Azure Web App. This test uses the exact same code. Instead of loading the InstrumentationKey from secrets.json, however, I've configured APPINSIGHTS_INSTRUMENTATIONKEY environment variable to have the key (via ApplicationSettings pane of the Web App in the portal).
I'm at a loss for why my events are not flowing to Application Insights via localhost debugger, but they are when deployed to a Web App.
Program.cs
public static void Main( string[] args )
{
BuildWebHost( args ).Run();
}
public static IWebHost BuildWebHost( string[] args ) =>
WebHost.CreateDefaultBuilder( args )
.UseStartup<Startup>()
.UseApplicationInsights()
.Build();
Startup.cs
var configurationBuilder = new ConfigurationBuilder()
.SetBasePath( hostingEnvironment.ContentRootPath )
.AddJsonFile( $"appsettings.{hostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true );
if ( hostingEnvironment.IsDevelopment() )
{
configurationBuilder.AddUserSecrets<Startup>( optional: true );
}
this.Configuration = configurationBuilder
.AddEnvironmentVariables()
.Build();
secrets.json
{
"ApplicationInsights": {
"InstrumentationKey": "omitted for StackOverflow"
}
}
my.csproj
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.1.1" />
<PackageReference Include="Microsoft.ApplicationInsights.Web" Version="2.5.1" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.0" />
launchSettings.json
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:2322/",
"sslPort": 44330
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "https://localhost:44330/",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"FrontDoor": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "https://localhost:44330/api/config",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:2323"
}
}
}
when you see appinsights events in the debugger output window, do those events say (unconfigured) in them? if that is present in the output window, that would mean that the sdk is running in debug, but not finding the instrumentation key in your appsettings.json (or in code) note that the application insights sdks don't look in usersecrets for this setting, only appsettings! (edit 5/28/2020: see OP's edit below, while this was the issue 2 years ago, if you use AddApplicationInsightsTelemetry instead of the obsolete UseApplicationInsights this limitation does not apply)
if the events in the debugger window do not say (unconfigured), the next step is to use something like Fiddler to watch your outbound http traffic, to make sure you're seeing outbound calls by the SDK going to dc.services.visualstudio.com, and that those outbound calls are succeeding. (and at this step, you can verify that the instrumentation key think you are using are using is the one the sdk is using to send the events)
if the events are being sent, and are using the ikey you have set, the last step is to verify that the ikey you're using is the one for the resource you're looking at in the portal. every once in a while, someone has an ikey for "dev" somewhere, and then is looking at a "prod" resource in the portal and not seeing the events they expect.
if you've gotten this far, with the events being sent, sent to the ikey you want, and verified the ikey is for the resource you expect it to be, then verify that there aren't any service outages or delays that might be affecting your data, which you can find at http://aka.ms/aistatus otherwise, you should see events normally in seconds~minutes depending on where in the world you are and what region your resource is in azure, etc.
OP edit for completeness of answer:
Indeed, I was hitting #1 and as John hinted in the comments, I needed to let AI SDK know about my iKey in another way. Instead of using UseApplicationInsights() in Program.cs, I've switched to using AddApplicationInsightsTelemetry(configuration) within StartUp.ConfigureServices(). The configuration passed along has my iKey loaded from secrets.json.
This is a known limitation, being fixed in the coming beta.
https://github.com/microsoft/ApplicationInsights-dotnet/issues/1882
Until then workaround is to use the AddApplicationInsights(IConfiguration) overlaod.
Starting from Microsoft.ApplicationInsights.AspNetCore version 2.15.0 this problem has been fixed.
For lower versions the overload services.AddApplicationInsightsTelemetry(Configuration) would read also from secrets.json.
User secrets and other configuration providers
If you want to store the instrumentation key in ASP.NET Core user
secrets or retrieve it from another configuration provider, you can
use the overload with a
Microsoft.Extensions.Configuration.IConfiguration parameter. For
example, services.AddApplicationInsightsTelemetry(Configuration);.
Starting from Microsoft.ApplicationInsights.AspNetCore version 2.15.0,
calling services.AddApplicationInsightsTelemetry() will automatically
read the instrumentation key from
Microsoft.Extensions.Configuration.IConfiguration of the application.
There is no need to explicitly provide the IConfiguration.
https://learn.microsoft.com/en-us/azure/azure-monitor/app/asp-net-core

How to Connect to Azure database using the standard dotnet web template

I am super excited to start developing .NET on my Mac but getting frustrated trying to figure it all out. So I have a WebApplication created by calling yo aspnet and out of the box it works great. It comes with a connection to a local db stored in the project. Where I am having trouble is connecting it to a remote DB hosted in my azure portal.
My Connection string below directly from my azure portal. I have updated my appsettings.json "DefaultConnection" property to this value (with the username and password missing below) and I am getting errors like "ArgumentException: Keyword not supported: 'server'." I have tried several different connection strings and none are working.
Admittedly I am new to all of this so I am probably missing something simple but in searching online I have yet to find the solution.
Server=tcp:mydbserver.database.windows.net,1433;Initial Catalog=LH;Persist Security Info=False;User ID={your_username};Password={your_password};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;
For reference here is my whole appsettings.json (without username & passwrod...)
{
"ConnectionStrings": {
//"DefaultConnection": "Data Source=LH.db"
"DefaultConnection": "Server=tcp:mydbserver.database.windows.net,1433;Initial Catalog=lighthouseFSQ;Persist Security Info=False;User ID={Username};Password={Password};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
},
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
Any help is greatly appreciated. FYI I did try this in Windows VS2015 and it worked fine.
By default, the dotnet new -t web tempalte uses SQLite database, so only changing the connection string is not sufficient to change the provider.
You also need to remove the Microsoft.EntityFrameworkCore.Sqlite package from project.json and replace it with Microsoft.EntityFramework.SqlServer (assuming you are using the SQLServer of Azure). Then in your Startup.cs you need to replace the
// Add framework services.
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(Configuration.GetConnectionString("DefaultConnection")));
with
// Add framework services.
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
and change the namespaces if necessary.
Update
In project.json you just need to change the dependency with Sqlite.
"dependencies": {
...
"Microsoft.EntityFrameworkCore.Sqlite": "1.0.1",
...
}
}
to
"dependencies": {
...
"Microsoft.EntityFrameworkCore.SqlServer": "1.0.1",
...
}
}
If there is also a Microsoft.EntityFrameworkCore.Sqlite.Design ch ange that too to Microsoft.EntityFrameworkCore.SqlServer.Design too, it's there for scaffolding etc.

Resources