Displaying an HTML error page in ASP.NET Core - asp.net-core

I would like to display an HTML error page when I catch a certain exception in my ASP.NET Core project. The page is stored in the project's root and I'm having trouble finding what I need to use in order to show this page. in this case, the application is already running and I would like the exception to be handled by redirecting the URL to the internally contained .html page.
What is the best practice for this?

If you want to execute custom error page,you could use UseStatusCodePagesWithReExecute and UseExceptionHandler middleware like below:
Controller:
public class ErrorController : Controller
{
[Route("Error/{statusCode}")]
public IActionResult StatusCodeError(int statusCode)
{
return Redirect("Index.html"); //Index.html located in wwwroot folder
}
}
Startup.cs:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseStatusCodePagesWithReExecute("/Error/{0}");
app.UseExceptionHandler("/Error/500");
app.UseHttpsRedirection();
app.UseStaticFiles();
//...
}

Error handling is built into ASP.NET Core. This docs page provides the overview.
The important bits are to configure the error handler within Configure method of Startup.cs:
app.UseExceptionHandler("/Error");
Then have a Razor page called Error.cshtml that handles and displays whatever content you'd like.

Related

Asp.Net Core 5 app.UseExceptionHandler("/Error") usage

I'm going to publish a ASP.NET Core 5 project. I couldn't find any documentation about how to correctly use app.UseExceptionHandler("/Error") in Startup.cs. I'm using Views folder for my .cshtml files. Should I put an Error.cshtml file globally there? If so, shouldn't a controller direct the user to error page, or Configure method can handle that?
if (env.IsDevelopment())
{
SeedDatabase.Seed();
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
Alternatively can I use the method like app.UseExceptionHandler("/Home/Error"); and put a method in HomeController.cs :
public IActionResult Error(){
return View();
}
Can this cover all errors and what will be the difference from putting only "/Error" to exception handler?

dotnet core change swagger.json server url wrong under subdir

I have a dotnet core webapi project that is setup with swagger.
Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddSwaggerGen();
...
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("./v1/swagger.json", "myapi.Api V1");
});
}
Controllers are like so:
[Route("api/[controller]/[action]")]
[ApiController]
[Authorize(Policy = "policyname")]
public class ThingController : ControllerBase
{
[HttpGet]
public async Task<ActionResult> GetThing()
{
....
}
}
This works fine locally and once deployed to the server and accessed directly (eg https://myservername/myapi/swagger/index.html can correctly make api calls to https://myservername/myapi/api/thing)
However we have an alias setup to access via https://myapp.company.com/services/myapi.
Now making direct api calls works eg https://myapp.company.com/services/myapi/api/thing returns the same as https://myservername/myapi/api/thing
Swagger UI displays correctly at https://myapp.company.com/services/myapi/swagger/index.html and it is loading swagger.json correctly but all api calls are made as https://myapp.company.com/myapi/api/thing i.e.. /services is missing from the api base url, needless to say these api calls fail.
Swagger.json contains the following:
"servers": [
{
"url": "/myapi"
}
],
I presume this should be /services/myapi and the rest should fall into place. How can I set this?
I've done some googleing and found plenty of questions asking how to move swagger ui to a new location (UseSwaggerUI(c => c.RoutePrefix) and some on how to move swagger.json to a new location (app.UseSwagger(c => c.RouteTemplate) but neither of them is what I want.
How can I configure swagger's server url at runtime? Preferably using local paths so it works on all environments (eg it 'just knows' its at https://myservername/myapi/, https://myapp.company.com/services/myapi/ or even https://localhost:5001/ and sets the base url as appropriate.)

Custom 500 error page fallback - ASP.NET Core Razor Pages

I created custom 500 error page in ASP.NET Core 3.0 Razor Pages application for environments different than development. The custom 500 page is using the same layout as the other pages and if some of the components which is added directly in the layout (like header/footer) errors then I can see server 500 error page, not my custom error page.
Would it be possible somehow to fallback to a completely static html page in this case? If so, how to do it?
Below are the middleware I am using at the moment.
Startup.cs:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Errors/Error500");
app.UseStatusCodePagesWithReExecute("/Errors/Error{0}");
}
}

Errors Thrown From View Component don't Show Error Page

I have an Asp.Net Core 2.0 application that is configured to show an Error Page in Production or use DeveloperExeptionPage.
If I throw an error directly from a controller, this works fine.
However if I throw an error from a ViewComponent it does not work. I get a blank page in the browser and when I look in the Developer Tools on Chrome, the page request just says status "failed" and "GET (page url) 200 ()" in the console.
In IE, I get "This Page cannot be display" with "Error Code: INET_E_DOWNLOAD_FAILURE"
Any help would be appreciated.
It's hard to know what is going wrong without seeing your ViewComponent's class and how you are invoking your view component.
That being said, the following works in a brand new application created with dotnet new mvc (and version 2.1.3 of the SDK).
.\Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseExceptionHandler("/Home/Error");
app.UseMvcWithDefaultRoute();
}
.\Views\Shared\Components\FooBar\Default.cshtml
<p>FooBarViewComponent</p>
.\Views\Home\Index.cshtml
#await Component.InvokeAsync("FooBar")
.\FooBarViewComponent.cs
public class FooBarViewComponent : ViewComponent {
public async Task<IViewComponentResult> InvokeAsync() {
throw new System.Exception("Exception in FooBar");
await Task.Delay(0);
return View();
}
}
Navigating to the home page reliably renders the "/Home/Error" view.

How to ignore routes in MVC6

I'm developing a very simple SPA style application and I don't want to use razor, so I just need it to serve up HTML files (from the wwwroot folder), except for when the js calls my API controllers. In Web API 2 you could get the router to ignore HTML files so they are served directly e.g.
config.Routes.IgnoreRoute("Html", "{whatever}.html/{*pathInfo}");
similar to this example: http://www.strathweb.com/2014/04/ignoring-routes-asp-net-web-api/ is the IgnoreRoute functionality just not implemented or has it been changed?
At the moment if I have app.UseMvc(); in my Startup.cs any get request to "/" gets me this exception:
An unhandled exception occurred while processing the request.
InvalidOperationException: The view 'Index' was not found. The following locations were searched:
/Views/Home/Index.cshtml
/Views/Shared/Index.cshtml.
Microsoft.AspNet.Mvc.Rendering.ViewEngineResult.EnsureSuccessful()
But when I leave it without MVC it serves up the index.html file when you request "/" - obviously my API controllers won't work then though.
I think if you want to serve index.html even when your MVC option is enabled? If so you have to change one setting.
When you enable MVC there is a default route added to search for Home/Index when your url is like http://localhost:yourport.
When you disable MVC it will serve index.html as no route is present in that case.
So if you want to serve index.html when MVC is enabled then add the following in Configure function before using MVC.
app.UseDefaultFiles(new Microsoft.AspNet.StaticFiles.DefaultFilesOptions() { DefaultFileNames = new[] { "index.html" } });
// your UseMVC goes here.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseMvc();
}