Probably your web.config file is wrong or is missing some tag. I solved my problem using the correct config tags for .NET 4.
<system.web>
<compilation debug="true" strict="false" explicit="true" targetFramework="4.0">
<assemblies>
<add assembly="System.Deployment, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="System.Web.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Transactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
</assemblies>
</compilation>
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID">
<namespaces>
<clear/>
<add namespace="System"/>
<add namespace="System.Collections"/>
<add namespace="System.Collections.Specialized"/>
<add namespace="System.Configuration"/>
<add namespace="System.Text"/>
<add namespace="System.Text.RegularExpressions"/>
<add namespace="System.Web"/>
<add namespace="System.Web.Caching"/>
<add namespace="System.Web.SessionState"/>
<add namespace="System.Web.Security"/>
<add namespace="System.Web.Profile"/>
<add namespace="System.Web.UI"/>
<add namespace="System.Web.UI.WebControls"/>
<add namespace="System.Web.UI.WebControls.WebParts"/>
<add namespace="System.Web.UI.HtmlControls"/>
</namespaces>
</pages>
<authentication mode="None"/>
</system.web>
The 500 Internal Server Error is a common issue when deploying an ASP.NET Core app on IIS. This error occurs when there is a problem with the server, preventing the application from processing the request properly. This error can have multiple causes, ranging from configuration issues to runtime errors in the application code. In this article, we will look at various methods to troubleshoot and resolve the 500 Internal Server Error in ASP.NET Core on IIS.
Method 1: Check the Event Logs
If you encounter a 500 Internal Server Error when deploying an ASP.NET Core app on IIS, you can use the Event Viewer to check the logs and find the root cause of the error. Here are the steps to follow:
-
Open the Event Viewer by typing «Event Viewer» in the Start menu search bar.
-
Navigate to «Windows Logs» > «Application».
-
Look for the event with the source «ASP.NET Core» and the level «Error».
-
Click on the event to view the details.
-
Check the «Event Data» section to find the error message and the stack trace.
-
Fix the error based on the error message and the stack trace.
For example, if you encounter a «FileNotFoundException», you can check if the file exists and the file path is correct.
System.IO.FileNotFoundException: Could not find file 'C:\inetpub\wwwroot\myapp\wwwroot\appsettings.json'.
You can also use the «Exception» field to get more details about the error.
System.InvalidOperationException: Unable to configure HTTPS endpoint. No server certificate was specified, and the default developer certificate could not be found or is out of date.
In this case, you can generate a new developer certificate or install a valid certificate.
By following these steps, you can quickly diagnose and fix the 500 Internal Server Error when deploying an ASP.NET Core app on IIS.
Method 2: Check the ASP.NET Core Version and Configuration
To check the ASP.NET Core version and configuration, follow these steps:
-
Open the command prompt and navigate to the directory where your ASP.NET Core app is published.
-
Run the following command to check the version of ASP.NET Core installed on the server:
- Check the runtime configuration of your ASP.NET Core app by navigating to the directory where your app is published and opening the
appsettings.json
file. Verify that the configuration matches the runtime environment of the server.
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*",
"Environment": "Production"
}
- Check the
web.config
file in the root directory of your ASP.NET Core app. Verify that theprocessPath
attribute of theaspNetCore
element points to the correct location of thedotnet.exe
file on the server.
<aspNetCore processPath="C:\Program Files\dotnet\dotnet.exe" arguments=".\MyApp.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" />
- Verify that the
stdoutLogFile
attribute of theaspNetCore
element points to a valid directory on the server where the ASP.NET Core app can write log files.
<aspNetCore processPath="C:\Program Files\dotnet\dotnet.exe" arguments=".\MyApp.dll" stdoutLogEnabled="true" stdoutLogFile="C:\inetpub\logs\LogFiles\MyApp\stdout" />
By following these steps, you should be able to identify and fix any issues with the ASP.NET Core version and configuration that may be causing the 500 internal server error on IIS.
Method 3: Debug the Application with Detailed Error Messages
To debug an ASP.NET Core app deployed on IIS that meets a 500 internal server error, you can use the following steps to enable detailed error messages:
- Open the web.config file of your ASP.NET Core app deployed on IIS.
- Add the following configuration under the
<system.webServer>
element:
<aspNetCore ...>
<environmentVariables>
<environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Development" />
</environmentVariables>
</aspNetCore>
- Save the web.config file and restart the IIS server.
- Reproduce the error in your ASP.NET Core app.
- Check the detailed error message by browsing to the URL that caused the error. The error message should now include detailed information about the error, including the stack trace.
Here is an example of how to add the configuration to the web.config file:
<configuration>
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\MyAspNetCoreApp.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" />
<httpErrors errorMode="Detailed" />
<aspNetCore ...>
<environmentVariables>
<environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Development" />
</environmentVariables>
</aspNetCore>
</system.webServer>
</configuration>
Note that adding the <httpErrors errorMode="Detailed" />
configuration will also display detailed error messages for non-ASP.NET Core errors.
That’s it! You should now be able to see detailed error messages for your ASP.NET Core app deployed on IIS.
Method 4: Investigate IIS Logs and Failed Request Tracing
If your ASP.NET Core app deployed on IIS meets a 500 internal server error, you can investigate the issue using IIS logs and Failed Request Tracing. Here are the steps:
-
Enable Failed Request Tracing
You can enable Failed Request Tracing by adding the following code to your web.config file:
<system.webServer> <tracing> <traceFailedRequests> <add path="*"> <traceAreas> <add provider="ASPNET" verbosity="Verbose" /> <add provider="WWW Server" areas="Authentication,Security,Filter,StaticFile,CGI,Compression,Cache,RequestNotifications,Module,Rewrite,WebSocket" verbosity="Verbose" /> </traceAreas> <failureDefinitions statusCodes="500" /> </add> </traceFailedRequests> </tracing> </system.webServer>
This will enable Failed Request Tracing for all paths and log requests that result in a 500 status code.
-
View the Failed Request Tracing logs
Failed Request Tracing logs can be viewed in the %SystemDrive%\inetpub\logs\FailedReqLogFiles folder. Open the log file for the failed request and look for any errors or warnings.
-
View the IIS logs
IIS logs can be viewed in the %SystemDrive%\inetpub\logs\LogFiles folder. Open the log file for the failed request and look for any errors or warnings.
-
Analyze the logs
Look for any errors or warnings in the logs that may indicate the cause of the 500 internal server error. Some common issues include missing dependencies, incorrect configuration settings, or issues with the application code.
-
Fix the issue
Once you have identified the cause of the 500 internal server error, fix the issue and redeploy your application.
That’s it! By following these steps, you can investigate and fix 500 internal server errors in your ASP.NET Core app deployed on IIS using IIS logs and Failed Request Tracing.
Method 5: Monitor the Application with Health Checks
To monitor the application with health checks, you need to follow the steps below:
-
Add the
Microsoft.AspNetCore.Diagnostics.HealthChecks
NuGet package to your project. -
In the
ConfigureServices
method of yourStartup.cs
file, add the following code:
services.AddHealthChecks();
- In the
Configure
method of yourStartup.cs
file, add the following code:
app.UseHealthChecks("/health");
This code adds a health check endpoint to your application at the /health
URL.
- In the
Configure
method of yourStartup.cs
file, add the following code to check the database connection:
app.UseHealthChecks("/health", new HealthCheckOptions
{
Predicate = check => check.Tags.Contains("database"),
ResponseWriter = async (context, report) =>
{
var result = JsonConvert.SerializeObject(
new
{
status = report.Status.ToString(),
errors = report.Entries.Select(e => new { key = e.Key, value = e.Value.Status.ToString() })
});
context.Response.ContentType = MediaTypeNames.Application.Json;
await context.Response.WriteAsync(result);
}
});
This code checks the database connection and returns the result in JSON format.
- In the
Configure
method of yourStartup.cs
file, add the following code to check the application’s overall health:
app.UseHealthChecks("/health", new HealthCheckOptions
{
Predicate = _ => true,
ResponseWriter = async (context, report) =>
{
var result = JsonConvert.SerializeObject(
new
{
status = report.Status.ToString(),
errors = report.Entries.Select(e => new { key = e.Key, value = e.Value.Status.ToString() })
});
context.Response.ContentType = MediaTypeNames.Application.Json;
await context.Response.WriteAsync(result);
}
});
This code checks the overall health of the application and returns the result in JSON format.
By monitoring the application with health checks, you can quickly identify any issues that may be causing the 500 internal server error. The health check endpoint provides a detailed report of the application’s health, including any errors or issues that may be affecting its performance.
The simplest way to return a 500 response is to use the Problem() helper method, like this:
[Route("[controller]")]
[ApiController]
public class MoviesController : ControllerBase
{
[HttpPost]
public IActionResult Save(Movie movie)
{
return Problem();
}
}
Code language: C# (cs)
This method returns an ObjectResult with status code 500 and a generic error message, which gets serialized to JSON and returned in the response body. The response looks like this:
500 - Internal Server Error
Content-Type: application/problem+json
Body:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.6.1",
"title": "An error occured while processing your request.",
"status": 500,
"traceId": "0HMDLK1UAAP5O:00000002"
}
Code language: plaintext (plaintext)
The ControllerBase class has many helper methods like Problem() that simplify returning responses. These have several optional parameters that you can use to customize the response. Internally, these helper methods return result objects. You can build and return these result objects yourself if you want. Sometimes that might even be necessary, such as if there’s not a helper method for what you’re trying to return.
In this article, I’ll show how to customize the 500 response, and then I’ll show examples of returning other response status codes (such as 400 – Bad Request).
Customizing the 500 response
The Problem() method has the following signature:
public ObjectResult Problem(string detail = null,
string instance = null,
int? statusCode = null,
string title = null,
string type = null);
Code language: C# (cs)
There are several optional parameters. You can customize the response by using these parameters, as I’ll show below.
Note: When you don’t pass in values for these parameters, it’ll use default values. This can lead to surprising response values. I recommend double-checking the responses during development. You can completely control what it returns if you need to.
Change the status code
The client can get the status code indicating that it’s an error response and deal with it appropriately. To change the status code, pass in a value for the statusCode parameter. For example, let’s say you want to return 501 – Not Implemented:
using Microsoft.AspNetCore.Http;
[Route("[controller]")]
[ApiController]
public class MoviesController : ControllerBase
{
[HttpPost]
public IActionResult Save(Movie movie)
{
return Problem(statusCode: StatusCodes.Status501NotImplemented);
}
}
Code language: C# (cs)
This generates the following response:
501 - Not Implemented
Content-Type: application/problem+json
Body:
{
"status": 501,
"traceId": "0HMDLKL0AFS4D:00000001"
}
Code language: plaintext (plaintext)
Note: You can hardcode the status code value (501), use integer constants from Microsoft.AspNetCore.Http.StatusCodes, or use the System.Net.HttpStatusCode enum (which you have to cast to an int).
Change the response body
The response body has several properties in it that you can control through parameters. For example, let’s say you want to add details about the problem:
[Route("[controller]")]
[ApiController]
public class MoviesController : ControllerBase
{
[HttpPost]
public IActionResult Save(Movie movie)
{
return Problem(detail: "Movie doesn't exist");
}
}
Code language: C# (cs)
This produces the following response. Notice that it added the detail property:
500 - Internal Server Error
Content-Type: application/problem+json
Body:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.6.1",
"title": "An error occured while processing your request.",
"status": 500,
"detail": "Movie doesn't exist",
"traceId": "0HMDLKRP86VKE:00000001"
}
Code language: plaintext (plaintext)
Completely customize the response
The Problem() method sets the content to a ProblemDetails object. The client can read this ProblemDetails JSON to get more information about the error. Let’s say you don’t want any of the ProblemDetails properties. One way to completely customize the response is to use the StatusCode() helper method:
using Microsoft.AspNetCore.Http;
[Route("[controller]")]
[ApiController]
public class MoviesController : ControllerBase
{
[HttpPost]
public IActionResult Save(Movie movie)
{
return StatusCode(StatusCodes.Status500InternalServerError, "Movie doesn't exist");
}
}
Code language: C# (cs)
This generates the following response:
500 - Internal Server Error
Content-Type: text/plain
Body:
Movie doesn't exist
Code language: plaintext (plaintext)
Building a response object
The helper methods provided by the ControllerBase class are convenient and simplify building the response. Internally, these mostly just build and return result objects (such as StatusCodeResult). You can build the result objects yourself if you want.
Here’s an example. Let’s say you want to return a 500 response with no content. In this case, you can return a ContentResult and only set the StatusCode.
using Microsoft.AspNetCore.Http;
[Route("[controller]")]
[ApiController]
public class MoviesController : ControllerBase
{
[HttpPost]
public IActionResult Save(Movie movie)
{
return new ContentResult()
{
StatusCode = StatusCodes.Status500InternalServerError
};
}
}
Code language: C# (cs)
This generates the response:
500 - Internal Server Error
Content-Length: 0
Code language: plaintext (plaintext)
There are several result types you can choose from (such as StatusCodeResult, ContentResult, ObjectResult, etc…). I usually pick ContentResult.
Examples of returning other response codes
ControllerBase has many helper methods that simplify returning responses. In this section, I’ll show examples of returning a few different response codes by using the helper methods.
200 – OK
If your method is returning an IActionResult, then you can return a 200 – OK response by using the Ok() helper method:
[Route("[controller]")]
[ApiController]
public class MoviesController : ControllerBase
{
[HttpPost]
public IActionResult Get(int id)
{
var movie = repository.GetMovie(id);
return Ok(movie);
}
}
Code language: C# (cs)
This generates the response:
200 - OK
Content-Type: application/json
Body:
{
"title": "Dune",
"yearReleased": 2021,
"score": 9
}
Code language: plaintext (plaintext)
400 – Bad Request
To return a 400 – Bad Request response, you can use the BadRequest() helper method:
[Route("[controller]")]
[ApiController]
public class MoviesController : ControllerBase
{
[HttpPost]
public IActionResult Save(Movie movie)
{
return BadRequest();
}
}
Code language: C# (cs)
This generates the response:
400 - Bad Request
Content-Type: application/problem+json
Body:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "Bad Request",
"status": 400,
"traceId": "0HMDLM4FOTSV3:00000001"
}
Code language: plaintext (plaintext)
With custom content:
return BadRequest(error: new { errorCode=12345 });
Code language: C# (cs)
This generates the response:
400 - Bad Request
Content-Type: application/json
Body:
{
"errorCode": 12345
}
Code language: plaintext (plaintext)
Returning any response code
Not all response codes have their own helper methods (like Problem() for 500) or result objects (like BadRequestResult for 400). When that’s the case, the simplest way to return any response code is to use the StatusCode() helper method, like this:
using Microsoft.AspNetCore.Http;
[Route("[controller]")]
[ApiController]
public class MoviesController : ControllerBase
{
[HttpPost]
public IActionResult Save(Movie movie)
{
return StatusCode(StatusCodes.Status429TooManyRequests);
}
}
Code language: C# (cs)
This generates the response:
429 - Too Many Requests
Content-Type: application/problem+json
Body:
{
"status": 429,
"traceId": "0HMDLMAQ7DNES:00000001"
}
Code language: plaintext (plaintext)
You can change the content via the value parameter:
return StatusCode(StatusCodes.Status429TooManyRequests,
value: "You've reached your limit for the day");
Code language: C# (cs)
This generates the response:
429 - Too Many Requests
Content-Type: text/plain
Body:
You've reached your limit for the day
Code language: plaintext (plaintext)
Related Articles
If you’ve stumbled upon this post, it most likely means that you’ve just published a new ASP.NET Core Web Application on a Windows web server using Internet Information Services (IIS) and you’ve got the following HTTP error 500.30 when trying to execute it:
HTTP Error 500.30 — ASP.NET Core app failed to start
Common solutions to this issue:
— The app failed to start
— The app started but then stopped
— The app started but threw an exception during startupTroubleshooting steps:
— Check the system event log for error messages
— Enable logging the application process’ stdout messages
— Attach a debugger to the application process and inspectFor more information visit: https://go.microsoft.com/fwlink/?LinkID=2028265
If we follow the Microsoft link we can see how such error happens when the worker process fails: the ASP.NET Core Module attempts to start the .NET Core CLR in-process, but it fails to start, thus preventing the app from running.
Unfortunately, the cause of a process startup failure might be due to a number of different reasons: the Microsoft guide suggest to look in the Application Event Log and/or in the ASP.NET Core Module stdout log, which will likely report some useful information regarding the problem. However, the most common failure conditions are:
- ASP.NET Core framework (or Hosting Bundle) is not present. Check if the proper version of the ASP.NET Core Hosting Bundle is installed on the target machine (and install it if it’s missing).
- Azure Key Vault lack of permissions. If you’re using the Azure Key Vault, check the access policies in the targeted Key Vault to ensure that the correct permissions are granted.
Furthermore, there’s an additional common cause of HTTP Error 500.30 which is not covered by the Microsoft guide: the wrong CPU architecture configured in the IIS Application Pool. Such error happens when you deploy a win-x64 app and try to have it published using a IIS Application Pool that supports 32-bit apps (and vice-versa). To fix that, you just have to change the IIS Application Pool configuration from the IIS Manager tool in the following way:
In the above example, we’re changing the IIS Application Pool from 32-bit to 64-bit, which is required if we need to publish a win-64 app.
Conclusion
That’s it, at least for now: we hope that this informative post can help other ASP.NET Core Developers and System Administrators stuck with the HTTP Error 500.30 when trying to deploy their ASP.NET Core Web Application on a Windows-IIS web server. This solution has also been shared in the following StackOverflow thread.
Сегодня обсудим, как на asp.net mvc можно настроить обработку ошибок 404, 500, ну и любых других. Рассмотрим на примере 404 и 500, как наиболее популярных и важных. Как вместо стандартного не очень красивого желтого окна ошибки показывать свои собственные красивые интересные страницы, и при этом как правильно отдавать код ошибки в браузер пользователя.
Казалось бы, задача довольно тривиальная и может быть решена написанием буквально пары строк кода. Действительно, так и есть, если вы используете любую популярную серверную технологию. Но только не ASP.NET. Если ваше приложение написано на ASP.NET MVC, и вы первый раз сталкиваетесь с проблемой обработки ошибок, очень легко запутаться и сделать неправильные настройки. Что впоследствии негативно отразится на продвижении сайта в поисковых системах, удобстве работы для пользователя, SEO-оптимизации.
Рассмотрим два подхода, как настроить страницы ошибок. Они в целом похожи, какой выбрать – решать вам.
Для начала вспомним, что означают наиболее популярные коды ошибок, которые отдает сервер.
Код ответа 200. Это значит что все ОК. Запрос клиента обработан успешно, и сервер отдал затребованные клиентом данные в полном объеме. Например, пользователь кликнул по гиперссылке, и в ответ на это в браузере отобразилась нужная ему информация.
Код ответа 404. Это означает, что запрошенный клиентом ресурс не найден на сервере. Например, указанная в адресе гиперссылки статья не найдена, или *.pdf файл был удален и теперь недоступен для скачивания.
Код ответа 500. Внутренняя ошибка на сайте. Что-то сломалось. Это может быть все что угодно, от неправильно написанного кода программистом, до отказа оборудования на сервере.
Допустим, мы только что создали новое веб-приложение типа MVC. На текущий момент, если никаких дополнительных действий для обработки ошибок не принимать, то стандартный сценарий обработки ошибок будет работать как нужно. В браузер пользователя будет отдаваться правильный код ошибки, пользователю будет показана стандартная страница с ошибкой и ее описанием.
Стандартная страница ошибки
Теперь займемся настройкой собственных страниц ошибок. При этом для нас важно не только показать пользователю красивую страницу ошибки, но также сохранить правильный код ответа сервера.
Вариант 1. Ссылка на статичные заранее подготовленные html-страницы.
Первым делом в файле web.config в разделе system.web добавляем новую секцию customErrors со следующими настройками:
web.config
<system.web>
<customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="~/404.aspx">
<error statusCode="404" redirect="~/404.aspx"/>
<error statusCode="500" redirect="~/500.aspx"/>
</customErrors>
...
</system.web>
Эта секция служит для обработки ошибок на уровне платформы ASP.NET.
Атрибут mode=»On» определяет, что пользовательские страницы ошибок включены. Также допустимы значения Off / RemoteOnly.
Атрибут redirectMode=»ResponseRewrite» определяет, следует ли изменять URL-адрес запроса при перенаправлении на пользовательскую страницу ошибки. Естественно, нам этого не нужно.
Атрибут defaultRedirect=»~/404.aspx» указывает на то, какая страница ошибки будет показана в случае возникновения кода ответа сервера, который мы не описали в настройках. Пусть при любых других ошибках пользователь будет думать, что страница не найдена.
И уже внутри этой секции мы определяем два кода, для которых у нас будут кастомные страницы ошибок.
Далее, как видно из настроек выше, нам понадобятся *.aspx файлы, на которые будет делаться редирект. Обратите внимание, что мы ссылаемся именно на *.aspx файлы, а не на *.html. Эти файлы являются проходными, служебными, в них содержатся настройки для ответа сервера. Содержимое файла 404.aspx:
404.aspx
<%@ Page Language="C#" %>
<%
var filePath = MapPath("~/404.html");
Response.StatusCode = 404;
Response.ContentType = "text/html; charset=utf-8";
Response.WriteFile(filePath);
%>
В коде выше мы указываем путь непосредственно до конечного *.html файла, а также дополняем настройки ответа сервера. Указываем код ответа, тип отдаваемого контента и кодировку. Если не указать кодировку, то браузер пользователя может интерпретировать ответ от сервера как не отформатированную строку, и, соответственно, не преобразует ее в html-разметку. А если не указать StatusCode = 404 , то получится следующая интересная ситуация:
Код ответа сервера отдается неверно
И хотя на рисунке выше нам показывается пользовательская страница с ошибкой, при этом код ответа 200 — это конечно же неверно. Когда-то давно на форумах Microsoft такое поведение зарепортили как баг. Однако Microsoft возразила, что это не баг, а фича и не стала ничего менять в будущих релизах ASP.NET. Поэтому приходится это исправлять вручную, и вручную в *.aspx файле в ответе сервера указывать код ответа 404.
Попробуйте собственноручно намеренно убрать какую-нибудь из объявленных на данный момент настроек из секции customErrors и понаблюдайте за результатом.
Также по аналогии создаем подобный *.aspx файл для ошибки 500.
И уже после этого нам нужно создать статичные html-файлы, соответственно для ошибок 404 и 500. Пусть они лежат в корне нашего проекта.
Статичные файлы расположены в корне проекта
Здесь же в файле web.config определяем раздел system.WebServer, если он еще не определен, и в нем объявляем секцию httpErrors:
web.config
<system.webServer>
<httpErrors errorMode="Custom" defaultResponseMode="File" defaultPath="c:\projects\mysite\404.html">
<remove statusCode="404" />
<remove statusCode="500" />
<error statusCode="404" path="404.html" responseMode="File" />
<error statusCode="500" path="500.html" responseMode="File" />
</httpErrors>
</system.webServer>
Эта секция служит для обработки ошибок на уровне сервера IIS. Суть в том, что иногда обработка запроса происходит непосредственно на уровне ASP.NET. А иногда ASP.NET просто определяет нужный код ответа и пропускает запрос выше, на уровень сервера. Такой сценарий может случиться, если, например, мы в действии контроллера возвращаем экземпляр класса HttpNotFound:
Или же когда система маршрутизации в MVC-приложении не может определить, к какому маршруту отнести запрошенный пользователем URL-адрес:
https://site.com/long/long/long/long/path
Для секции httpErrors важно отметить следующее. Так как мы ссылаемся на статичные *.html файлы, то и в качестве значений для нужных атрибутов здесь также указываем File . Для атрибута defaultPath необходимо указать абсолютный путь до файла ошибки. Относительный путь именно в этом месте работать не будет. Сам атрибут defaultPath определяет файл, который будет выбран для всех других ошибок, которые мы явно не указали. Но здесь есть одна небольшая проблема. Дело в том, что этот атрибут по умолчанию заблокирован на сервере IIS Express. Если вы разрабатываете свое приложение именно на локальном сервере, то это ограничение нужно снять. Для этого в директории своего проекта нужно найти файл конфигурации сервера и удалить этот атрибут из заблокированных, как это показано на рисунке:
Расположение файла applicationhost.config
Также проверьте папку App_Start. Если вы создали не пустое приложение, а работаете над реальным проектом, там может находиться класс FilterConfig, в котором регистрируются все глобальные фильтры в приложении. В методе регистрации удалите строчку кода, где регистрируется HandleErrorAttribute, в нашем случае он не понадобится.
Вот такой комплекс мер нужно предпринять, чтобы настроить обработку ошибок 404, 500, и любых других. Это настройки в файле web.config, и добавление в наш проект статичных файлов.
Вариант 2. Обработка ошибок с использованием специального контроллера.
Второй подход немного отличается от первого. Здесь нам не понадобится секция customErrors, так как обработку всех ошибок мы будем передавать сразу из приложения на уровень сервера, и он уже будет решать что делать. Можно удалить или закомментировать эту секцию в файле web.config.
Далее создадим специальный контроллер, который будет принимать все ошибки, которые мы хотим обрабатывать:
public class ErrorController : Controller
{
public ActionResult NotFound()
{
Response.StatusCode = 404;
return View();
}
public ActionResult Internal()
{
Response.StatusCode = 500;
return View();
}
}
Также создадим соответствующие представления с нужной нам красивой разметкой.
Также в файле web.config нам нужно изменить настройки в секции httpErrors. Если раньше мы ссылались на статичные html-файлы, то теперь мы будем обращаться по указанным URL, которые мы определили в ErrorController’е, чтобы именно там обрабатывать ошибки:
web.config
<httpErrors errorMode="Custom" existingResponse="Replace" defaultResponseMode="ExecuteURL" defaultPath="/Error/NotFound">
<remove statusCode="404"/>
<remove statusCode="500"/>
<error statusCode="404" path="/Error/NotFound" responseMode="ExecuteURL"/>
<error statusCode="500" path="/Error/Internal" responseMode="ExecuteURL"/>
</httpErrors>
Вариант 3. Фильтр HandleErrorAttribute
Замечу, что есть еще один способ взять под свой контроль обработку ошибок в приложении – это наследоваться от стандартного класса HandleErrorAttribute и написать свой фильтр. Но это уже более частный случай, когда нужно реализовать какую-то особенную логику при возникновении той или иной ошибки. В большинстве же более менее стандартных приложений наша проблема решается двумя выше описанными способами и в этом фильтре нет необходимости. Более подробную информацию, как работать с классом HandleErrorAttribute можно найти в официальной документации в интернете по этой ссылке.
Итого
Мы посмотрели на два разных подхода, которые можно применить при обработке ошибок на платформе ASP.NET. Опять же повторюсь, что если для вас не принципиально настраивать собственные страницы ошибок, то лучше не изменять эти настройки, так как даже одна упущенная деталь или неверно сконфигурированный параметр может очень сильно навредить репутации вашего сайта для конечного пользователя и в поисковых системах.