When using the new template for ASP.NET Core 6.0, which includes var builder = WebApplication.CreateBuilder(args); the DeveloperExceptionPageMiddleware is automatically added. I would like to not use this middleware so that I can provide a consistent error response in all environments.
Is there anyway to put my custom error handling before this middleware, or prevent it from being included? Or to remove it after it's been included?
Currently you can't disable DeveloperExceptionPageMiddleware in minimal hosting model for development environment since it is set up without any options to configure. So options are:
Use/switch back to generic host model (the one with Startups) and skip the UseDeveloperExceptionPage call.
Do not use development environment
Setup custom exception handling. DeveloperExceptionPageMiddleware relies on the fact that exception was not handled later down the pipeline so adding custom exception handler right after the building the app should do the trick:
app.Use(async (context, func) =>
{
try
{
await func();
}
catch (Exception e)
{
context.Response.Clear();
// Preserve the status code that would have been written by the server automatically when a BadHttpRequestException is thrown.
if (e is BadHttpRequestException badHttpRequestException)
{
context.Response.StatusCode = badHttpRequestException.StatusCode;
}
else
{
context.Response.StatusCode = 500;
}
// log, write custom response and so on...
}
});
Using custom exception handler page with UseExceptionHandler also should (unless the handler itself throws 🙂) work.
The easiest way to skip DeveloperExceptionPageMiddleware is not using the Development environment.
You can modify the Properties/launchSettings.json file, change ASPNETCORE_ENVIRONMENT to anything but Development.
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:43562",
"sslPort": 44332
}
},
"profiles": {
"api1": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7109;http://localhost:5111",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "MyDevelopment"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "MyDevelopment"
}
}
}
}
In your app, change all builder.Environment.IsDevelopment() to builder.Environment.IsEnvironment("MyDevelopment").
Related
I was trying to follow this guide on ASP.NET Web Api and Angular. I followed it step by step with the only difference being I used .NET version 7 for the Web Api instead of 6. When I ran the project for the first time I got this inthe output:
<e> [webpack-dev-server] [HPM] Error occurred while proxying request localhost:4200/weatherforecast
to https://localhost:5290/ [EPROTO] (https://nodejs.org/api/errors.html#errors_common_system_errors)
In the guide they addressed this issue by saying
If you see this issue, most likely the frontend started before the backend. Once you see the backend command prompt up and running, just refresh the Angular App in the browser.
So I made sure the Api was running, then reloaded the browser, but the error stayed. I can't seem to find enybody with the same problem.
launchSettings.json
{
"profiles": {
"http": {
"commandName": "Project",
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true,
"applicationUrl": "http://localhost:5290"
},
"https": {
"commandName": "Project",
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true,
"applicationUrl": "https://localhost:7294;http://localhost:5290"
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
},
"$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:32492",
"sslPort": 44306
}
}
}
Proxy.conf.js
const PROXY_CONFIG = [
{
context: [
"/weatherforecast",
],
target: "https://localhost:5290",
secure: false
}
]
module.exports = PROXY_CONFIG;
Also I think the guide must be outdated, so if anyone knows of a newer guide, please point me to it.
I'm trying to get acces (I mean POSTing,GETing...) to my backend API written using asp.net Core and registred in the machine which has the following ip address (for example : 192.168.1.80) from a machine that has the followingg ip address (for ex: 192.168.1.71), When I run my app using the following launchSettings.json :
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iis": {
"applicationUrl": "http://localhost/ServerMonitoringApi",
"sslPort": 0
},
"iisExpress": {
"applicationUrl": "http://localhost:9999",
"sslPort": 0
}
},
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "api/Alerting",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"ServerMonitoringApi": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "api/Alerting",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:9999;http://localhost:5000"
}
}
}
I can use it if I stay in the same machine i.e : https://localhost:9999, but when I try to get the data from the distant machine where I use https://192.168.1.80:9999 it doesnt work for me, do I need to configure something? Or allow the acces to my port(9999).
I'm a newbie be gentel, thanks for your help :)
You need to specify more urls when building the WebHost in Program.cs, otherwise Kestrel isn't going to listen outside localhost.
var host = WebHost.CreateDefaultBuilder(args)
.UseUrls("http://....") // url of your server using server name or IP
.UseStartup<Startup>()
.Build();
Of course, do not forget to remove that line when going into production.
I am trying to change http://localhost:5001/api/values route but the program is stuck this url.
I read this solutions
How to change the default controller and action in ASP.NET Core API?
How to redirect root to swagger in Asp.Net Core 2.x?
https://medium.com/quick-code/routing-in-asp-net-core-c433bff3f1a4
Everyone write same thing but not work for me.
My launchSetting.json file is
{ "$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:54650",
"sslPort": 44382
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"ShoppingBasketAPI": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
I tried to change app.UseMvc();
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/routing?view=aspnetcore-2.2
this is also not working.Where does api/values come from? I can't figure out .
My controller attribute route is
[Route("api/[controller]/[action]")]
When you create new ASP.Net Core Web API project you will see that in project property there is launchUrl setting that set to "api/values" path. So you can change it to what ever url you want or you can change in your launchSetting.json file
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:54356",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "api/values",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"WebApplication4": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "api/values",
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
So you will see in profiles section there will be 2 config. One is for IIS express (when using Visual Studio to run your code) and WebApplication4 (when you run project using dotnet run) so you can change into
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:54356",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"WebApplication4": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
So when you use VS to run the project or dotnet run command is will always serve the swagger url first.
I am using VSCode and is happening the same to me, but on Windows.
I am just enhancing a bit the answer here.
I have tried VS2019 and it worked in that IDE, so it is supposely to do with VSCode.
I have searched for other answers and I found this.
vscode launch.json debug and open specific url
What fixed my issue was to go to .vscode/launch.json file and append:
"launchBrowser": {
"enabled": true,
"args": "${auto-detect-url}",
"windows": {
"command": "cmd.exe",
"args": "/C start ${auto-detect-url}/swagger"
}
as Anton Dremin describes, just add the above into the configurations section.
The problem is because of Visual Studio for Mac. I was able to get the correct url to chance Run With>Custom Configuration > Run Action --> Debug .Net Core Debugger
How to get configuration of started application in C# .Net Core
I know that I can do it like that:
public static string Get_Configuration() {
string conf = "Release";
#if DEBUG
conf = "Debug";
#endif
return conf;
}
But it doesn’t look very good, any ideas how to do it most beautifully?
I guess what you need is build platform.
Build platform is embedded in the DLL / EXE at the time of compilation.
I am not sure what is the purpose and what exactly should be input to the API you want to create. Hence I am throwing couple of options which I believe would help you to solve the issue.
Option 1: Use Assembly Attribute
In this you can conditionally apply assembly configuration attribute to the assembly.
Then at runtime, you can check the assembly attributes applied to the DLL / EXE.
#if (Debug || DEBUG)
[assembly: AssemblyConfiguration("Debug")]
#else
[assembly: AssemblyConfiguration("Release")]
#endif
Option 2: Using C# code
There is a method is from Scott Hanselman's blog which takes assembly name and decides if the assembly was built using Release mode.
public static int GetBuildType(string AssemblyName)
{
Assembly assm = Assembly.LoadFrom(AssemblyName);
object[] attributes = assm.GetCustomAttributes(typeof(DebuggableAttribute), false);
if (attributes.Length == 0)
{
Console.WriteLine(String.Format("{0} is a RELEASE Build....", AssemblyName));
return 0;
}
foreach (Attribute attr in attributes)
{
if (attr is DebuggableAttribute)
{
DebuggableAttribute d = attr as DebuggableAttribute;
Console.WriteLine(String.Format("Run time Optimizer is enabled : {0}", !d.IsJITOptimizerDisabled));
Console.WriteLine(String.Format("Run time Tracking is enabled : {0}", d.IsJITTrackingEnabled));
if (d.IsJITOptimizerDisabled == true)
{
Console.WriteLine(String.Format("{0} is a DEBUG Build....", AssemblyName));
return 1;
}
else
{
Console.WriteLine(String.Format("{0} is a RELEASE Build....", AssemblyName));
return 0;
}
}
}
return 3;
}
Option 3: PowerShell Script
On the same blog, you can find some powershell scripts which can also be used.
Based on your purpose and ease, you can select any one of the option.
Hope this helps.
I think you mean environment if I'm not wrong.
Here's what you can do, in SolutionExplorer go to:
Properties -> lunchSettings.json
In your launchSettings.json, you'll find a json object which contain a section named Profiles.
Under profile add the environments you want.
For example, in the first place your Profiles will be like that:
"profiles": {
"ProjectName.Development": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "api/Locations",
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}}
Change your Profiles to be like this:
"profiles": {
"ProjectName.Development": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "api/Locations",
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"ProjectName.Local": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "api/Locations",
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Local"
}
},
"ProjectName.Production": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "api/Locations",
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Production"
}
}}
After finishing. Add to your solution explorer:
appSettings.Development.json,
appSettings.Local.json,
appSettings.Production.json.
And add your configuration to these files.
Then you can navigate between your environments and run whatever you want from the tool bar as you can see in the following image:
I am running unit tests as part of an ASP.NET Core MVC solution. The version of .NET Core is 2.1 to be exact.
I have created a profile section in a launchSettings.json file that contains environment variables that I would like to have loaded and injected by the test runner, so that the environment variables are available and can contain specific values when running unit tests.
The launchSettings.json from my ASP.NET Core MVC project is added to my unit test project as a link, and the properties are set to Build Action - None, Copy to output folder - Copy Always.
The file gets copied to my output folder, but I'm not sure how to get the test runner to use this file with the UnitTesting profile. I have tried using the word "Test" as the profile name, nothing seems to work.
Here is a sample launchSettings.json file:
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:62267/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"MigrationHistoryTableName": "MigrationHistory",
"ConnectionStringName": "EFConnectionString",
"Redis__SSL": "True",
"Redis__Port": "6380",
"Redis__InstanceName": "RedisDev",
"Redis__AbortConnect": "False",
"Redis__ConnectionString": "{URI}:{Port},password={Password},ssl={SSL},abortConnect={AbortConnect}"
}
},
"MyDataServices": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"MigrationHistoryTableName": "MigrationHistory",
"ConnectionStringName": "EFConnectionString",
"Redis__SSL": "True",
"Redis__Port": "6380",
"Redis__InstanceName": "RedisDev",
"Redis__AbortConnect": "False",
"Redis__ConnectionString": "{URI}:{Port},password={Password},ssl={SSL},abortConnect={AbortConnect}"
},
"applicationUrl": "http://localhost:4080/"
},
"UnitTesting": {
"commandName": "Executable",
"executablePath": "test",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"MigrationHistoryTableName": "MigrationHistory",
"ConnectionStringName": "EFConnectionString",
"Redis__SSL": "True",
"Redis__Port": "6380",
"Redis__InstanceName": "RedisDev",
"Redis__AbortConnect": "False",
"Redis__ConnectionString": "{URI}:{Port},password={Password},ssl={SSL},abortConnect={AbortConnect}"
}
}
}
}
I understand that by default the launchSettings.json file is ignored in git. We will check in our code with a development version of this file that will contain an example of the settings that are expected to be available in a development environment.
Thank you kindly for taking the time to read this and help out!
I wrote this static loader for now, but that's not ideal:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace MyNamespaceHere.Services.Common.Utilities
{
public static class LaunchSettingsLoader
{
public static void LaunchSettingsFixture(string launchSettingsPath = "Properties\\launchSettings.json", string profileName = "UnitTesting")
{
using (var file = File.OpenText(launchSettingsPath))
{
var reader = new JsonTextReader(file);
var jObject = JObject.Load(reader);
var allprofiles = jObject
.GetValue("profiles", StringComparison.OrdinalIgnoreCase);
// ideally we use this
var variables = jObject
.GetValue("profiles", StringComparison.OrdinalIgnoreCase)
//select a proper profile here
.SelectMany(profiles => profiles.Children())
//.Where(p => p.Value<String> == profileName)
.SelectMany(profile => profile.Children<JProperty>())
.Where(prop => prop.Name == "environmentVariables")
.SelectMany(prop => prop.Value.Children<JProperty>())
.ToList();
Console.WriteLine(variables?.Count);
var profilesDictJToken = allprofiles.ToObject<Dictionary<string, JToken>>();
var unitTestingProfile = profilesDictJToken[profileName];
var unitTestingProfileDictJToken = unitTestingProfile.ToObject<Dictionary<string, JToken>>();
var environmentVariables = unitTestingProfileDictJToken["environmentVariables"];
var environmentVariablesList = environmentVariables.ToList();
foreach (var variable in environmentVariablesList)
{
var name = ((JProperty)variable).Name;
var value = ((JProperty)variable).Value.ToString();
Environment.SetEnvironmentVariable(name, value);
}
}
}
}
}
I have created a package that might be able to help you: https://www.nuget.org/packages/DotNet.Project.LaunchSettings
You can find the source here: https://github.com/andygjp/DotNet.Project.LaunchSettings
I have a similar use case to you - I want to test different environments and I keep the logon details to these environments in the launchSettings.json.
This is how I use it:
async Task Example()
{
var launchSettings = VisualStudioLaunchSettings.FromCaller();
var profiles = launchSettings.GetProfiles();
var profile = profiles.FirstOrEmpty();
var client = await AppEnvironment.FromEnvironment(profile.EnvironmentVariables).CreateClient();
// use the client
}
It assumes launchSettings.json is in the usual place:
MyProject -> Properties -> launchSettings.json
However, I could add the functionality to load launch settings from a specified file path if you would find it useful.
The example above uses the first profile it finds, however, you can also use a particular profile.
Hope it helps.
Another solution for using environment variables in unit tests, for either mstest or xunittest, is through the ".runsettings" file provided for the platform:
See link below:
https://stackoverflow.com/a/68531200/4593944