The client has disconnected; The specified network name is no longer available. (0x80070040) - asp.net-core

I have noticed in the log file the following exception The client has disconnected. The possibility is very rare- ~3 times in a week so its hard to reproduce. Application runs on IIS windows server 2019.
The middleware witch handles exception:
public class RequestHandlingMiddleware
{
private readonly RequestDelegate _next;
public RequestHandlingMiddleware
(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext httpContext, IWallesterLogger logger)
{
try
{
await _next(httpContext); //<- This line throws an exception
var rawRequestBody = await (new StreamReader(httpContext.Request.Body).ReadToEndAsync());
await logger.Log(WallesterLogSection.RequestInfoLog, httpContext.Request.Path.Value,
new
{
httpContext.Request.Path.Value,
httpContext.Request.Method,
rawRequestBody,
httpContext.Request.Headers
}
);
}
catch (Exception ex)
{
await HandleExceptionAsync(httpContext, ex, logger);
throw;
}
}
private async Task HandleExceptionAsync
(HttpContext context, Exception exception, IWallesterLogger logger)
{
await logger.Log(exception, WallesterLogSection.Exception);
}
}
// Extension method used to add the middleware to the HTTP request pipeline.
public static class LoggerkMiddlewareExtensions
{
public static IApplicationBuilder UseLoggerMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<RequestHandlingMiddleware>();
}
}
Program.cs:
// Add services to the container.
var mocking = builder.Configuration.GetValue<bool>("Mocking");
var MockingDb = builder.Configuration.GetValue<bool>("MockingDb");
if (MockingDb)
{
builder.Services.AddDbContext<ApplicationDbContext>(x => x.UseInMemoryDatabase(databaseName: "ApplicationDb"));
}
else
{
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
}
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddControllersWithViews();
builder.Services.AddSingleton<IConfiguration>(builder.Configuration);
builder.Services.AddMemoryCache();
builder.Logging.ClearProviders();
builder.Logging.AddConsole();
var logger = new LoggerConfiguration()
.ReadFrom.Configuration(builder.Configuration)
.WriteTo.File($"logs/{DateTime.Now.ToString("dd-MM-yyyy-HH-mm-ss")}-logs.txt", rollingInterval: RollingInterval.Day)
.Enrich.FromLogContext()
.CreateLogger();
builder.Logging.AddSerilog(logger);
var app = builder.Build();
app.UseDeveloperExceptionPage();
app.UseStaticFiles();
app.UseLoggerMiddleware(); // <- add middleware logger
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
app.Run();
And the controller action it tried to reach looks like this:
[HttpPost("event")]
public async Task<IActionResult> PostEvent(
[FromBody] object obj)
Full exception callstack:
Microsoft.AspNetCore.Connections.ConnectionResetException: The client has disconnected
---> System.Runtime.InteropServices.COMException (0x80070040): The specified network name is no longer available. (0x80070040)
--- End of inner exception stack trace ---
at Microsoft.AspNetCore.Server.IIS.Core.IO.AsyncIOOperation.GetResult(Int16 token)
at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContext.ReadBody()
at System.IO.Pipelines.Pipe.GetReadResult(ReadResult& result)
at System.IO.Pipelines.Pipe.ReadAsync(CancellationToken token)
at System.IO.Pipelines.Pipe.DefaultPipeReader.ReadAsync(CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContext.ReadAsync(Memory`1 memory, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.IIS.Core.HttpRequestStream.ReadAsyncInternal(Memory`1 buffer, CancellationToken cancellationToken)
at System.Text.Json.JsonSerializer.ReadFromStreamAsync(Stream utf8Json, ReadBufferState bufferState, CancellationToken cancellationToken)
at System.Text.Json.JsonSerializer.ReadAllAsync[TValue](Stream utf8Json, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContext bindingContext)
at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value, Object container)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at WebApp.Middleware.RequestHandlingMiddleware.InvokeAsync(HttpContext httpContext, IWallesterLogger logger) in C:\Projects\Pasts\PNS\Wallester\WebApp\Middleware\RequestHandlingMiddleware.cs:line 19
at WebApp.Middleware.RequestHandlingMiddleware.InvokeAsync(HttpContext httpContext, IWallesterLogger logger) in C:\Projects\Pasts\PNS\Wallester\WebApp\Middleware\RequestHandlingMiddleware.cs:line 44
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
From the callstack line:19 is code in the middleware await _next(httpContext); and line:44 is throw command in the catch block.
My question would be what could cause this error, and is there anything we could change to fix it?

Related

System.InvalidOperationException: There is already an open DataReader associated with this Connection which must be closed first

I'm getting this error when calling the following block of code below. Everything I have seen related to this error on SO is due to people calling the using block, which I am not, but there could be some code behind the scenes I'm not aware of getting duplicated? I'm also not sure how to find what connection is being duplicated here. Anyone with some expertise able to assist on this issue? My stack trace is below as well.
if (await _userManager.IsInRoleAsync(user, role.Name))
public class UserRolesModel : PageModel
{
private readonly UserManager<IdentityUser> _userManager;
private readonly SignInManager<IdentityUser> _signInManager;
private readonly RoleManager<IdentityRole> _roleManager;
private readonly IAdminView _adminView;
public UserRolesModel(UserManager<IdentityUser> userManager,
SignInManager<IdentityUser> signInManager,
RoleManager<IdentityRole> roleManager,
IAdminView adminView)
{
_userManager = userManager;
_signInManager = signInManager;
_roleManager = roleManager;
_adminView = adminView;
}
public EmployeeDto Employee { get; set; }
public ManageUserRolesDto UserRoles { get; set; }
public async Task OnGetAsync(string userId)
{
var userRoleList = new List<UserRolesDto>();
var user = await _userManager.FindByIdAsync(userId);
foreach (var role in _roleManager.Roles)
{
var userRolesDto = new UserRolesDto()
{
RoleName = role.Name
};
if (await _userManager.IsInRoleAsync(user, role.Name))
{
userRolesDto.Selected = true;
}
else
{
userRolesDto.Selected = false;
}
userRoleList.Add(userRolesDto);
}
UserRoles = new ManageUserRolesDto()
{
UserId = userId,
UserRoles = userRoleList
};
var employeeData = await _adminView.GetEmployeeDataByAspId(userId);
var viewModel = new EmployeeViewDto
{
Employee = employeeData
};
Employee = new EmployeeDto
{
EmployeeAspId = employeeData.AspUserId,
EmployeeViewDto = viewModel
};
}
public async Task<IActionResult> OnPostAsync(string id, ManageUserRolesDto userRoles)
{
var user = await _userManager.FindByIdAsync(id);
var roles = await _userManager.GetRolesAsync(user);
var result = await _userManager.RemoveFromRolesAsync(user, roles);
result = await _userManager.AddToRolesAsync(user, userRoles.UserRoles.Where(x => x.Selected).Select(y => y.RoleName));
var currentUser = await _userManager.GetUserAsync(User);
await _signInManager.RefreshSignInAsync(currentUser);
await Data.Seeds.DefaultUsers.SeedSuperAdminAsync(_userManager, _roleManager);
return RedirectToPage("/Admin/Index");
}
}
Stack Trace
System.InvalidOperationException: There is already an open DataReader associated with this Connection which must be closed first.
at Microsoft.Data.SqlClient.SqlCommand.<>c.<ExecuteDbDataReaderAsync>b__169_0(Task`1 result)
at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.InitializeReaderAsync(DbContext _, Boolean result, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore`9.IsInRoleAsync(TUser user, String normalizedRoleName, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Identity.UserManager`1.IsInRoleAsync(TUser user, String role)
at Navrae.WebApp.Pages.RoleManager.UserRolesModel.OnGetAsync(String userId) in C:\Users\Work Laptop\source\repos\Navrae\Navrae.WebApp\Pages\RoleManager\UserRoles.cshtml.cs:line 45
at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.ExecutorFactory.NonGenericTaskHandlerMethod.Execute(Object receiver, Object[] arguments)
at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeHandlerMethodAsync()
at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeNextPageFilterAsync()
at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Rethrow(PageHandlerExecutedContext context)
at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeInnerFilterAsync()
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
As suggested by Lasse V. Karlsen, use .ToList() to close the data reader. Some changes I have to introduce for this fix is mentioned below.
Include ToList()
var dbData = dbContext.Table.Where(x=>x.ID=x).ToList(); //Include .ToList()
Include dbContext.Update(model)
foreach(var data in dbData)
{
//do work
dbContext.Update(data); //Update model
dbContext.SaveChanges(); //Save it now or later
}
dbContext?.Dispose(); //depends on your code structure.
Hope this helps. The MARS could also be an option, but I have not tried it as the ToList() solution solved my problem.

ASP.NET Core 5 application cannot find view error

I've created an ASP.NET Core 5 application project in Visual Studio 2019.
The requirement is that the views should not be precompiled.
So I set the RazorCompileOnPublish to false:
<RazorCompileOnPublish>false</RazorCompileOnPublish>
in the .csproj file.
After publishing the project, the Views folder was copied to the published directory.
But at runtime, I got the following error.
System.InvalidOperationException: The view 'Index' was not found. The following locations were searched:
/Views/Home/Index.cshtml
/Views/Shared/Index.cshtml
at Microsoft.AspNetCore.Mvc.ViewEngines.ViewEngineResult.EnsureSuccessful(IEnumerable1 originalLocations) at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor.ExecuteAsync(ActionContext context, ViewResult result) at Microsoft.AspNetCore.Mvc.ViewResult.ExecuteResultAsync(ActionContext context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeResultAsync>g__Logged|21_0(ResourceInvoker invoker, IActionResult result) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|29_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker) at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task) at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.HandleException(HttpContext context, ExceptionDispatchInfo edi) at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication1 application)
dbug: Microsoft.AspNetCore.Server.Kestrel[9] *
The program.cs and Startup.cs files are as follows:
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration) {
Configuration = configuration;
}
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
services.AddControllersWithViews();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
}
else {
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints => {
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
//endpoints.MapRazorPages(); //Has no effect
});
}
}
public class Program {
public static void Main(string[] args) {
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) {
Console.WriteLine($"ContentRoot set to: {Directory.GetCurrentDirectory()}");
var hostBuilder = Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder => {
webBuilder.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>();
});
return hostBuilder;
}
}
Please help. Thanks in advance
This setting can be used in .net core 2.x, but cannot enable runtime compilation in .net core 5.
In this case, you can use AddRazorRuntimeCompilation to enable runtime compilation.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews()
.AddRazorRuntimeCompilation();
}
The another way is to enable runtime compilation conditionally.
public Startup(IConfiguration configuration,IWebHostEnvironment webHostEnvironment)
{
Configuration = configuration;
Env = webHostEnvironment;
}
//...
public IWebHostEnvironment Env { get; set; }
public void ConfigureServices(IServiceCollection services)
{
IMvcBuilder builder = services.AddRazorPages();
if (!Env.IsDevelopment())
{
builder.AddRazorRuntimeCompilation();
}
services.AddControllersWithViews();
}
And you can refer to this document.
I edit Index.cshtml in editor.
Then save it in publish folder and start the project. It compiled as this.

How to filter out stack trace information from Rest API and simply return 'Status Code: 500; Internal Server Error'?

I have an .NET 5 wepapi. I have created a global exception handler attribute that I put on my base controller class. It looks like this
public override void OnException(ExceptionContext context)
{
// All user exceptions implement IWebApiException
if (context.Exception is IWebApiException webApiException)
{
// Then return a problem detail
ObjectResult result = new ObjectResult(new ProblemDetails
{
Type = webApiException.Type,
Title = webApiException.Title ?? ReasonPhrases.GetReasonPhrase(webApiException.Status),
Status = webApiException.Status,
Detail = webApiException.Detail,
Instance = webApiException.Instance,
})
{
StatusCode = webApiException.Status
};
result.ContentTypes
.Add(new
MediaTypeHeaderValue(newMicrosoft.Extensions.Primitives.StringSegment("application/problem+json")));
context.Result = result;
}
base.OnException(context);
}
The idea is that any exception intentionally thrown by the developer will implement IWebApiException and return standard problem details. However, then an exception is thrown that does not implement IWebApiException then the Rest API returns the entire stack trace to the caller and the response looks like this:
System.Exception: Test
at WebApplication1.Controllers.WeatherForecastController.Get() in C:\Dev\Projects\odiam-dot-net-api-starter\API\Controllers\WeatherForecastController.cs:line 58
at lambda_method14(Closure , Object , Object[] )
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ExceptionContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Builder.Extensions.UsePathBaseMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Instead I wish to return a simple message that looks like this:
Status Code: 500; Internal Server Error
What is the easiest way I can accomplish this while maintaining my global exceptions attribute and not having to wrap every action in try catch and return new StatusCodeResult(StatusCodes.Status500InternalServerError))?
The solution was simpler than I anticipated. I have ended up creating a middleware:
public class ErrorHandlingMiddleware
{
private readonly RequestDelegate next;
public ErrorHandlingMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await next(context);
}
catch (Exception ex)
{
await HandleException(context, ex);
}
}
private static Task HandleException(HttpContext context, Exception ex)
{
// If the exception is not user based
if (ex is not IWebAPiException)
{
// 500 if unexpected
HttpStatusCode code = HttpStatusCode.InternalServerError;
context.Response.ContentType = "text/plain";
context.Response.StatusCode = (int)code;
}
return context.Response.WriteAsync("Status Code: 500; Internal Server Error");
}
}
Register the middleware in the pipeline:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseCors(APIConstants.Cors.AllowAll);
//app.UseDeveloperExceptionPage(); <= remove this line to ensure middleware is used
}
app.UseMiddleware<ErrorHandlingMiddleware>();
...
}
Since all user thrown exceptions should implement IWebApiException, if the exception does NOT implement it, then just return internal server error 500.

API don't return CurrentUser. returning 500 internal server error

Startup.cs File Configuration
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<DataContext>(options =>
{
options.UseSqlite(Configuration.GetConnectionString("DefaultConnection"));
});
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy", policy =>
{
policy.AllowAnyHeader().AllowAnyMethod().WithOrigins("http://localhost:3000");
});
});
services.AddMediatR(typeof(list.Handler).Assembly);
services.AddMvc(opt => {
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
opt.Filters.Add(new AuthorizeFilter(policy));
})
.AddFluentValidation(cfg => cfg.RegisterValidatorsFromAssemblyContaining<create>());
var builder = services.AddIdentityCore<AppUser>();
var identityBuilder = new IdentityBuilder(builder.UserType, builder.Services);
identityBuilder.AddEntityFrameworkStores<DataContext>();
identityBuilder.AddSignInManager<SignInManager<AppUser>>();
services.AddScoped<IJwtGenerator, JwtGenerator>();
services.AddScoped<IUserAccessor, UserAccessor>();
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["TokenKey"]));
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(
opt => {
opt.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = key,
ValidateAudience = false,
ValidateIssuer = false
};
}
);
}
My UserDefine Middleware
public class ErrorHandlingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ErrorHandlingMiddleware> _logger;
public ErrorHandlingMiddleware(RequestDelegate next, ILogger<ErrorHandlingMiddleware> logger)
{
_logger = logger;
_next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
await HandleExceptionAsync(context, ex, _logger);
}
}
private async Task HandleExceptionAsync(HttpContext context, Exception ex,
ILogger<ErrorHandlingMiddleware> logger)
{
object errors = null;
switch(ex)
{
case RestException re:
logger.LogError(ex, "Rest Error");
errors = re.Errors;
context.Response.StatusCode = (int)re.Code;
break;
case Exception e:
logger.LogError(ex, "Server Error");
errors = string.IsNullOrWhiteSpace(e.Message) ? "Error" : e.Message;
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
break;
}
context.Response.ContentType = "application/json";
if(errors != null)
{
var result = JsonConvert.SerializeObject(new {
errors
});
await context.Response.WriteAsync(result);
}
}
}
RestException File
public class RestException : Exception
{
public RestException(HttpStatusCode code, object errors = null)
{
Code = code;
Errors = errors;
}
public HttpStatusCode Code { get; }
public object Errors { get; }
}
UserAccessor File
public class UserAccessor : IUserAccessor
{
private readonly IHttpContextAccessor _httpContextAccessor;
public UserAccessor(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public string GetCurrentUsername()
{
var username = _httpContextAccessor.HttpContext.User?.Claims?.FirstOrDefault( x=> x.Type == ClaimTypes.NameIdentifier)?.Value;
return username;
}
}
this is my CurrentUser File that return CurrentUser Information to API
public class CurrentUser
{
public class Query : IRequest<User> { }
public class Handler : IRequestHandler<Query, User>
{
private readonly IJwtGenerator _jwtGenerator;
private readonly IUserAccessor _userAccessor;
private readonly UserManager<AppUser> _userManager;
public Handler(UserManager<AppUser> userManager, IJwtGenerator jwtGenerator, IUserAccessor userAccessor)
{
_userAccessor = userAccessor;
_jwtGenerator = jwtGenerator;
_userManager = userManager;
}
public async Task<User> Handle(Query request, CancellationToken cancellationToken)
{
var user = await _userManager.FindByNameAsync(_userAccessor.GetCurrentUsername());
return new User
{
DisplayName = user.DisplayName,
Username = user.UserName,
Token = _jwtGenerator.CreateToken(user),
Image = null
};
}
}
}
I tested this through POSTMAN and the server returning And VsCode showing these error
500 Internal Server Error
fail: API.MiddleWare.ErrorHandlingMiddleware[0] Server Error System.ArgumentNullException: Value cannot be null. (Parameter 'userName') at Microsoft.AspNetCore.Identity.UserManager1.FindByNameAsync(String userName)
at Application.Users.CurrentUser.Handler.Handle(Query request, CancellationToken cancellationToken)
in C:\Users\NOYON\source\repos\reactivity\Application\Users\CurrentUser.cs:line 28
at MediatR.Pipeline.RequestExceptionProcessorBehavior2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate1 next)
at MediatR.Pipeline.RequestExceptionProcessorBehavior2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate1 next)
at MediatR.Pipeline.RequestExceptionActionProcessorBehavior2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate1 next)
at MediatR.Pipeline.RequestExceptionActionProcessorBehavior2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate1 next)
at MediatR.Pipeline.RequestPostProcessorBehavior2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate1 next)
at MediatR.Pipeline.RequestPreProcessorBehavior2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate1 next)
at API.Controllers.UserController.CurrentUser() in C:\Users\NOYON\source\repos\reactivity\api\Controllers\UserController.cs:line 28
at lambda_method(Closure , Object )
at Microsoft.Extensions.Internal.ObjectMethodExecutorAwaitable.Awaiter.GetResult()
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor
executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask1 actionResultValueTask) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync() --- End of stack trace from previous location where exception was thrown --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync() --- End of stack trace from previous location where exception was thrown --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at API.MiddleWare.ErrorHandlingMiddleware.Invoke(HttpContext context) in C:\Users\NOYON\source\repos\reactivity\api\Middleware\ErrorHandlingMiddleware.cs:line 25
When I called user from a UserController then API say's
{"errors":"Value cannot be null. (Parameter 'userName')"}
Why this GetCurrentUser() return username as null? isn't this a correct instruction to get current user?
Because you don't post your Startup.cs file so I don't know what your current JWT configs. However, if you use sub property in JWT as username, you should add this line below
x.TokenValidationParameters = new TokenValidationParameters
{
...,
NameClaimType = ClaimTypes.NameIdentifier
};
If you want to get exactly one key in JWT token, you can get by following code
var handler = new JwtSecurityTokenHandler();
var jwtTokenStr = httpRequest.Headers["Authorization"].ToString().Replace("Bearer ", string.Empty, System.StringComparison.Ordinal);
var jwtToken = handler.ReadJwtToken(jwtTokenStr);
// Get Sub by this line
jwtToken.Claims.FirstOrDefault(a => a.Type == JwtClaimTypes.Subject)?.Value
GetCurrentUsername() implementation correctly. After trying several time changes its working right as I want. Although It's now the same as I declared here. I don't know why this happened.

ASP .NET Core 2.0 deployment unable to connect with WCF service in production

I have a .NET core app in that has connected WCF Service, everything works fine in the dev environment, but in the deployment environment the service is not connecting.
I published the ASP .NET core project and hosted it in IIS, the published app also contains the ConnectedService.json file:
{
"ProviderId": "Microsoft.VisualStudio.ConnectedService.Wcf",
"Version": "15.0.20628.921",
"GettingStartedDocument": {
"Uri": "https://go.microsoft.com/fwlink/?linkid=858517"
},
"ExtendedData": {
"Uri": "http://localhost:8759/Design_Time_Addresses/CECWcfServiceLib/CECService/text/mex",
"Namespace": "CEC_WCF_Service",
"SelectedAccessLevelForGeneratedClass": "Public",
"GenerateMessageContract": false,
"ReuseTypesinReferencedAssemblies": true,
"ReuseTypesinAllReferencedAssemblies": true,
"CollectionTypeReference": {
"Item1": "System.Array",
"Item2": "System.Runtime.dll"
},
"DictionaryCollectionTypeReference": {
"Item1": "System.Collections.Generic.Dictionary`2",
"Item2": "System.Collections.dll"
},
"CheckedReferencedAssemblies": [],
"InstanceId": null,
"Name": "CEC_WCF_Service",
"Metadata": {}
}
}
The error I get is
System.NullReferenceException: Object reference not set to an instance of an object.
at AspNetCore.Views_Home_CEC_Dashboard.ExecuteAsync() in D:\Users\sajja\source\repos\CECDashboard\CECDashboard\Views\Home\CEC_Dashboard.cshtml:line 9
at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context)
at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, Boolean invokeViewStarts)
at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context)
at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, String contentType, Nullable`1 statusCode)
at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ActionContext actionContext, IView view, ViewDataDictionary viewData, ITempDataDictionary tempData, String contentType, Nullable`1 statusCode)
at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor.ExecuteAsync(ActionContext context, ViewResult result)
at Microsoft.AspNetCore.Mvc.ViewResult.ExecuteResultAsync(ActionContext context)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultAsync(IActionResult result)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResultFilterAsync[TFilter,TFilterAsync]()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResultExecutedContext context)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultFilters()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
at Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Am I missing a deployment configuration because this works fine in dev environment.
[Update] Code in the HomeController
public ActionResult CEC_Dashboard()
{
try
{
CEC_WCF_Service.CECServiceClient cECService = new CEC_WCF_Service.CECServiceClient();
var task1 = Task.Run(async () => await cECService.OpenAsync());
task1.Wait();
var task2 = Task.Run(async () => await cECService.GetAccountsAsync());
task2.Wait();
var accountsInfo = task2.Result.ToList();
var task3 = Task.Run(async () => await cECService.GetAccountStatsOnAccountAsync(1));
task3.Wait();
var account_Stats = task3.Result.ToList();
ViewData["Account_Stats"] = account_Stats;
ViewData["accountsInfo"] = accountsInfo;
ViewData["DefaultAccountsView"] = accountsInfo.Find(o => o.AccountId == 1);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return View();
}
So, after days of research I figured out the problem. As originally thought, the problem was indeed related to the WCF configuration for production deployment.
So, here is what I did after research on multiple threads.
1- Injected IConfiguration in HomeController
public class HomeController : Controller
{
private IConfiguration configuration;
public HomeController(IConfiguration iConfig)
{
configuration = iConfig;
}
<...More Class Code here ...>
}
2- Added the settings in appsettings.json
"MyService": {
"EndpointUrl": "http://localhost:8082/hello?wsdl"
}
3- Here is what was missing while doing production deployment. The Reference.cs file has the address of the dev time address, so I did all the above to mitigate and be able to load the production address at run time.
This method is referred in one of the post Reference Post
//
var EndPoint = configuration.GetSection("MyService").GetSection("EndpointUrl").Value;
System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
result.MaxBufferSize = int.MaxValue;
result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
result.MaxReceivedMessageSize = int.MaxValue;
result.AllowCookies = true;
//
CEC_WCF_Service.CECServiceClient cECService = new CEC_WCF_Service.CECServiceClient(result, new System.ServiceModel.EndpointAddress(EndPoint));
var task1 = Task.Run(async () => await cECService.OpenAsync());
task1.Wait();
This resolved the issue for production deployment!