Asp.net core 2 deployment to IIS10 (Windows Server 2016) - windows-server-2016

I am getting following error when i tried to publish Asp.net core 2 application to IIS10 on Windows Server 2016.
I build asp.net core 2 project using dotnet publish -c release and that works with dotnet PriceCore.dll
Following is Program.cs file
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace PriceCore
{
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
}
}
And following is web.config generated by publish output
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\PriceCore.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" />
</system.webServer>
</configuration>
And i am getting following error page.
I also installed URL rewrite module 2 to server and also asp.net core sdk to server.
Can you please suggest where i am doing wrong.

Related

Connect NLog To Database Using Azure KeyVault Connection String In NetCore 3.1

My nlogconfig file is writing fine to a text file. It is also writing to a database when I include the connection string in appsettings.json. Now that we are ready to move to production, I am not going to be housing the connection string in appsettings.json.
However, the problem is that I do not know how to connect mynlogconfig file to a connection string that is located in Azure KeyVault.
How do I take this line of code in nlogconfig
connectionString="${configsetting:item=ConnectionStrings.DefaultConnection}"
and reference the connection string in Azure KeyVault?
My nlogconfig file:
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true">
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
<add assembly="NLog.Appsettings.Standard"/>
</extensions>
<targets>
<!-- local file target -->
<target name="fileTarget"
xsi:type="File"
fileName="C:\Nlog\logs\meLog.txt"
layout="
-------------- ${level} (${longdate}) --------------${newline}
${newline}
Call Site: ${callsite}${newline}
Exception Type: ${exception:format=Type}${newline}
Exception Message: ${exception:format=Message}${newline}
Stack Trace: ${exception:format=StackTrace}${newline}
Additional Info: ${message}${newline}" />
<target xsi:type="Database"
name="dbTarget"
connectionString="${configsetting:item=ConnectionStrings.DefaultConnection}"
commandText="INSERT INTO Logs(CreatedOn,Message,Level,Exception,StackTrace,Logger,Url) VALUES (#datetime,#msg,#level,#exception,#trace,#logger,#url)">
<parameter name="#datetime" layout="${date}" />
<parameter name="#msg" layout="${message}" />
<parameter name="#level" layout="${level}" />
<parameter name="#exception" layout="${exception:format=#}" />
<parameter name="#trace" layout="${stacktrace}" />
<parameter name="#logger" layout="${logger}" />
<parameter name="#url" layout="${aspnet-request-url}" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Error" writeTo="dbTarget" />
<logger name="*" minlevel="Error" writeTo="fileTarget"/>
</rules>
</nlog>
My Program.cs file which is getting the database connection string from Azure KeyVault:
using Azure.Extensions.AspNetCore.Configuration.Secrets;
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using WebApplication6.Models;
namespace WebApplication6
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, config) =>
{
string MyClientID = "1MyClientID";
string MyTenantID = "1MyTenantID";
string MyClientSecretID = "1MyClientSecretID";
ClientSecretCredential credential =
new ClientSecretCredential(MyTenantID, MyClientID, MyClientSecretID);
var secretClient = new SecretClient(new Uri("https://somerandomurivault.vault.azure.net/"),
credential);
config.AddAzureKeyVault(secretClient, new KeyVaultSecretManager());
config.Build();
})
.ConfigureServices((hostContext, services)=>
{
var databaseConnectionString = hostContext.Configuration.GetValue<string>("databaseConnectionString");
services.AddDbContext<AppDbContext>(options =>
{
options.UseSqlServer(databaseConnectionString);
});
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
I tried to set the connection string to a global variable, but I had no way of referencing this global variable in the nlogconfig file.

.NET 2.0 Console App - Reading app settings

I am trying to get a .NET console application (Core 2.0) to read from an appsetting.json file. I have a webapi project that works fine with the following:
services.Configure<WebAppSettings>(Configuration.GetSection("WebAppSettings"));
But in the console app it says:
'ServiceCollection' does not contain a definition for 'Configure' and no extension method 'Configure' accepting a first argument of type 'ServiceCollection' could be found (are you missing a using directive or an assembly reference?)
I have the following packages installed in the console app project:
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.0.0" />
Here is the full Program.cs class:
using System;
using System.IO;
using Cam.Checker.Services;
using Cam.Common;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace Cam.Checker
{
class Program
{
public static IConfigurationRoot Configuration { get; set; }
static void Main(string[] args)
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json");
//.AddJsonFile($"appsettings.{env.EnvironmentName}.json", true, true);
Configuration = builder.Build();
var services = new ServiceCollection();
services.AddTransient<ICheckerService, CheckerService>();
// app settings
services.Configure<WebAppSettings>(Configuration.GetSection("WebAppSettings"));
var provider = services.BuildServiceProvider();
}
}
}
Thank you!
You need to add the NuGet package Microsoft.Extensions.Options.ConfigurationExtensions to get the Configure extension method.

Referencing .net framework assemblies in .net core 2 that rely on the ConfigurationManager

We have some legacy 4.5.2 class libraries that make common use of ConfigurationManager.AppSettings[key]
Is it possible to reference these within a .net core 2 application so that the config is correctly patched up under the hood?
I.e. the old calls into ConfigurationManager.AppSettings[key] correctly read the config, either from json or xml, but within the .netcore2 app.
If I port the keys of question to appSettings.json then the call into ConfigurationManager.AppSettings always returns null.
An example would be:
{
"Logging": {
"IncludeScopes": false,
"Debug": {
"LogLevel": {
"Default": "Warning"
}
},
"Console": {
"LogLevel": {
"Default": "Warning"
}
}
},
"appSettings": {"test": "bo"},
"test": "hi"
}
And then:
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2", ConfigurationManager.AppSettings["test"] , ConfigurationManager.AppSettings["appSettings:test"] };
}
Will display:
["value1","value2",null,null]
The setup you are looking for is possible and the settings can be kept as-is in app.config.
I have a .NET 4.5.2 class library "MyLibrary" and a .NET Core 2.0 web application "WebApp" referencing the full .NET framework 4.6.1.
MyLibrary
has an assembly reference to System.Configuration
has a class Foo which reads an appsetting with key foo
WebApp
has a project reference to MyLibrary
has an assembly reference to System.Configuration
has an app.config file containing the appSettings section. (App.config is by default present in a .NET Core 2.0 web application project.)
uses in instance of Foo, calls its GetSomething method by which the value bar gets assigned to the variable something.
All other files and settings are the default ones. Here below are the ones mentioned above.
MyLibrary project
.NET 4.5.2
Foo.cs
using System;
using System.Configuration;
namespace PFX
{
public class Foo
{
public String GetSomething()
{
String r = ConfigurationManager.AppSettings["foo"];
return r;
}
}
}
WebApp project
.NET Core 2.0.1 referencing full .NET framework 4.6.1.
WebApp.csproj
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net461</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.ViewCompilation" Version="2.0.4" PrivateAssets="All" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.3" />
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="2.0.3" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.4" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MyLibrary\MyLibrary.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="System.Configuration" />
</ItemGroup>
</Project>
App.config
<configuration>
<runtime>
<gcServer enabled="true"/>
</runtime>
<appSettings>
<add key="foo" value="bar"/>
</appSettings>
</configuration>
Program.cs
using System;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
namespace WebApp
{
public class Program
{
public static void Main(string[] args)
{
PFX.Foo foo = new PFX.Foo();
String someting = foo.GetSomething(); // bar
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(String[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
}

IIS 7 cannot route requests: error 404, file not found

I've created my first owin/web.api REST service.
Something super simple just to test some features.
I've created an empty project with Visual Studio 2013 and installed a these packages:
Microsoft.AspNet.WebApi.Client
Microsoft.AspNet.WebApi.Core
Microsoft.AspNet.WebApi.Owin
Microsoft.Owin
Microsoft.Owin.Diagnostics
Microsoft.Owin.Host.SystemWeb
Newtonsoft.Json
Owin
This is my startup class:
[assembly: OwinStartup(typeof(OwinO.Startup))]
namespace OwinO
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
app.UseWebApi(config);
app.UseWelcomePage("/");
app.UseErrorPage();
}
}
}
and this is my Api Controller:
[RoutePrefix("api/v1")]
public class TestController : ApiController
{
[HttpGet]
[Route("test")]
public async Task<IHttpActionResult> Get()
{
string name = "Mister";
string sayHello = string.Empty;
Task<string> t = new Task<string>(() =>
{
sayHello = string.Format("Hello {0}", name);
return sayHello;
});
t.Start();
await t;
return Ok(new string[] { sayHello });
}
}
My Web.Config:
<system.web>
<compilation debug="true" targetFramework="4.5.1" />
<httpRuntime targetFramework="4.5.1" />
</system.web>
<system.webServer>
<!--<modules runAllManagedModulesForAllRequests="true" />-->
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
Nothing really too complicated.
PROBLEM:
This Web.Api service works everywhere.
I've tested it on my PC with IIS Express (8.0) and my IIS 7.5 (Windows 7).
I've deployed it to my hosting provider (Arvixe) and it works.
I've deployed it on a server (Windows 2008 Server R2) and it works.
The problem it does not work where it should work.
My client's server is Windows 2008 sp2 (32 bit) with IIS 7.
I've managed to startup Owin but requests cannot be routed.
I cannot access the address: [server ip]/api/v1/test
WHAT I'VE TRIED:
I've checked the server's configuration:
Framework 4.5.1 is installed.
IIS is up and running (I've got other ASP.NET MVC web apps installed)
I've tried to remove the custom routing prefix:
[RoutePrefix("api/v1")]
I've checked the IIS log and the requests reach IIS.
It's just it does not know how to route.
To cross-check the problem I've created a simple web.api without Owin (with the same routing system) and it works.
The same Owin app self-hosted works.
There is not fix for this.
I've spent a good amount of time trying to find a solution or a way to fix it.
After the server upgrade everything worked as expected.

Custom httpModule is not logging to Windows Logs

I have a problem with logging an message to EventViewer\WindowsLogs using a custom HTTPModule class. I've already try to run Visual Studio with admin rights, I also tried from IIS 6.0. It doesn't crash, it just doesn't add any code. Below it's the module class and the config file.
HttpModule
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Diagnostics;
namespace Chapter_V.HttpModules
{
public class MyHttpModule : IHttpModule
{
public void Init(HttpApplication application)
{
application.AuthenticateRequest += new EventHandler(OnAuthentication);
}
private void OnAuthentication(object sender, EventArgs e)
{
string name = HttpContext.Current.User.Identity.Name;
EventLog log = new EventLog();
log.Source = "My First HttpModule";
log.WriteEntry(name + " was authenticated !");
}
public void Dispose()
{
}
}
}
web.config
<?xml version="1.0"?>
<configuration>
<system.web>
<httpModules>
<add name="MyHttpModule" type="Chapter_V.HttpModules.MyHttpModule,ChapterV"/>
</httpModules>
</system.web>
<system.webServer>
<modules>
<add name="MyHttpModule" type="Chapter_V.HttpModules.MyHttpModule,ChapterV"/>
</modules>
</system.webServer>
</configuration>
Do you have any ideea about this issue? (this is only for study purposes)
Provided the user identity on your application pool has the rights to create event log entries.
Try running the following script:
eventcreate /ID 1 /L APPLICATION /T INFORMATION /SO "My First HttpModule" /D "My first log"
This will create a new event source named "My First HttpModule" under APPLICATION event log as INFORMATION event type.
Not sure of the exact reasons why, but a source must already exist (be created) in the event log before it can be used in code.
Source of information is here

Resources