Logging errors in asp.net mvc, OnException method not enough? - c#

I am logging errors in my controllers method:
protected override void OnException(ExceptionContext filterContext)
But if I make a type in my view page, or enter a route that doesn't exist, it doesn't seem to log that erorr?

Use Elmah logging for that. No code required, just configuration. Elmah logs errors automatically in memory, xml, or a database, and provides a very nice userinterface for reviewing the errors.
See Scott Hanselman's explanation, and the official documentation, Using Elmah with ASP.NET MVC

Thats because its a pipeline and you want to log at a different scope, to log this error add the following to your global.asax:
public override void Init()
{
base.Error+=new EventHandler(MvcApplication_Error);
base.Init();
}
The pipeline is basically this:
incomming request
Hits IIS/ ASP.net
then the routing engine
then the controllers
then the views
so you need to get your error handlers in place before routing takes place to catch them.

Related

Why does middleware generate error in this way?

I'm a beginner in ASP.NET Core, just a question on how middleware generate error.
I'm reading a book that explain the importance of order when you configure middleware:
But I'm a little bit confused, for the second scenario, why can't the image resizing middleware produce an error like:
Because it will be logical for a middleware to generate an error before calling next():
public class ImageResizeMiddleware
{
private readonly RequestDelegate _next;
public ImageResizeMiddleware (RequestDelegate next) { _next = next }
public Task Invoke(HttpContext context)
{
... // if an error occurs here, then 500 should be added to the context here
await next(context); // control passed to the error handling middleware
}
}
So if an error occurs before next(context), then the error handling middleware can see 500 in HttpContext, no?
It depends! Does it make sense for an error to be propagated further in to the pipeline and possibly overwritten by another middleware/controller?
For an image resizing middleware I would expect the handler to check whether the request should be handled by and if not only then pass the request on to the next handler. If the request matches and is handled by the middleware it doesn't make sense to propagate the request further in to the pipeline to potentially be overwritten by something else and should instead return immediately once the response is written. This would mean that the error handling middleware would never be invoked and would not get a chance to prettify/log the error.
Imagine if authentication/authorisation middleware didn't short-circuit the pipeline and return immediately! You could end up with unauthenticated/unauthorised requests to potentially access resources they shouldn't have access to.
Simply put, if an error occurs then the middleware should return and not propagate the request further in to the pipeline.
The idea behind middleware is similar to how Unix commands are supposed to do one thing and do [that] well. By removing the need for each middleware to produce proper error responses, you are removing the need to duplicate the logic all over the place.
If you just look at the default error handling middleware, there are multiple ways to configure it: You could simply return a failure status code, you could have some handler that write directly to the response, you could also have a Razor view that is being displayed to show the user a nice error message.
If each middleware would now be responsible to generate this response, then each middleware would have to be able to do that. But middleware is usually designed to be rather independent: An authentication middleware does not need to care whether you even have Razor views in your application, and especially not how it could render an authentication failure using Razor. Instead, middlewares can rely on standard control mechanisms (e.g. exceptions) and just assume that someone else will hopefully take care of it.
And if you have the error handling middleware early in your pipeline, then that middleware can take care of it. And you only need to configure once how an error should be handled. And if a fancy Razor view should be rendered and returned to the user, then this can be done in this one place.

How to redirect user from OWIN middleware?

I have middleware used for authentication purposes and need to distinguish users by the type if they are internal or external. After this I want to redirect external users to custom error page, because they should not have access to particular section of my site.
I wanted to throw HttpResponseException with my custom status code and handle it by linking in web config's section customErrors with my error page. However I cannot use custom status code this way and to use one of the existing codes is bad idea in my case.
To be honest I am quite new to OWIN middleware and I am not even sure what to google. I will be most grateful for hints how to solve such situation.
Hey take a look at this:
public void Configuration(IAppBuilder app)
{
ConfigureApp(app);
//Some other code here
if (_helper.IsNew())
{
Debug.Write("This is a new guy. Redirect him to the setup page permanently");
var ctx = new OwinContext();
ctx.Response.Redirect("/Setup");//This is how I redirect from Startip.cs
}
}
Observe the code where I am checking in IF for truthy, on true I will create a new OWIN CONTEXT and do redirect there.
I can also specify the redirection status code: 301/302. But without that also the above code works just fine
You should be able to set response code (303 See Other) to the response object in middle-ware and a location header to where you want to redirect user.
When you do that based you you business logic you should not call next function and user will be redirected to new location (if no other middle-ware down the stack will change the response).
Remember to register your middle-ware before web api or mvc.
You can google for web api building custom middleware. Here is an example article you could find Writing Custom Middleware for ASP.NET.

ASP.NET detection of HttpHandler MVC vs. WebForms

I'm trying to understand and learn the architecture and pipeline of ASP.NET. So far I understand the architectural overview:
on how we get from client to the IIS webserver (request)
via ISAPI extension to the ASP.NET runtime
from there on into the HTTP Pipeline
and ASP.NET calling the HttpModules and HttpHandler
in case of using MVC, selecting the MvcHandler
which is returned by the MvcRouteHandler
etc etc
Now what I don't understand (or can't find any resource on the web documentating this part), is how does the asp.net runtime detect which HttpHandler it has to select for it's request? So how does it know based on my Visual Studio solution that it's an MVC application for example? How does it figure it out that it should use the MvcHttpHandlers? Is there an assembly scan with Reflection somewhere in the HTTP pipeline? Because it certainly isn't a configuration telling the runtime to use the MvcHandler, or is it?
So basically at what exact point is the HttpContext.CurrentHandler being set?
Application_Start
When the request arrives to IIS and the endpoint corresponds to an
Asp.Net application, then the first event raised is the
Application_Start in the System.Web.HttpApplication object.
RouteTable.Routes.Add
Into this event of an Mvc app you can set the routing rules that do
match endpoint urls with Controllers and Actions methods
in the application and the relative IRouteHandler object type,
that will be typeof(MvcRouteHandler).
(see Scott Guthrie post)
HttpApplication.MapRequestHandler
Therefore, soon after that, when the routing table has been setted up,
in the subsequents events (or better in the methods that compose the
pipeline orchestrated by the Asp.Net Framework under IIS control
(integrated pipeline)) of the Asp.Net http request management,
when it needs to know how to manage the http request itself
(HttpApplication.MapRequestHandler), it get parsed the url in
the HttpContext object against the rules in the routing table,
and when it get found a matching, it is instatiated the right type of
its handler, MvcRouteHandler in our case, which will return the
IHttpHandler object by the method GetHttpHandler(RequestContext): MvcHandler .
(see Msdn MvcRoutHandler.GetHttpHandler)
MvcHandler.ProcessRequest
MvcHandler in turn, will give start to the real MVC request handling
through the Asp.Net pipeline event ProcessRequest: and so will
be instatiated the right Controller through the
ControllerFactory, and will be called the Execute method of the Controller abstract base class of the instatiated
controller object, and finally the right Action through the
ActionInvoker.
(see Msdn MvcHandler.ProcessRequest, and The Asp.Net Mvc pipeline)
final note on RouteCollection.MapRoute The Visual Studio starter template for MVC projects creates project that use MapRoute extension method
instead of RouteTable.Routes.Add. This method is very useful
because avoids to have to use always typeof(MvcRouteHandler)
expression when adding new url routing to the project.
(see Asp.Net Routing and Asp.Net Mvc)

ASP.NET MVC: Check database connectivity on application startup

1- Sometimes my SQL Server is down for maintenance, so when I try to run my ASP.NET MVC application i face the yellow error screen with error network-related or instance-specific error occurred while establishing a connection to SQL Server.
Since I don't know the sequence of events in ASP.NET MVC I want to know where I should check connectivity so can I redirect user to a view informing him/her about this situation (instead of displaying this error page).
I saw this answer in asp.net forum but I couldn't understand how can I handle this inside global.asax.
2- Is it possible to do some changes which for every database connection error I can redirect user to that information page? I mean is it possible to define global exception handler for database connection error?
P.S. My connectionString in web.config is named DefaultConnection.
I think you can prepare a global filter(if you have many controllers and don't want to decorate each with an attribute) and just use it to check what kind of exception has been thrown and e.g. redirect user to some custom view:
public class SqlExceptionFilter: IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
// Do your logic
}
}
And then just register it in Global.asax in Application_Start() method:
GlobalFilters.Filters.Add(new SqlExceptionFilter());

Handling exceptions from action filters and orchard framework

Overriding ErrorPage.cshtml allows you to create custom error page for exceptons thrown from controllers, is there a way to handle exceptions thrown from filters? For example I would like to have custom page for anti forgery exceptions.
You can utilize exception filters. Just create your own FilterProvider and have it implement IExceptionFilter. Put all custom logic inside OnException(filterContext) method.
Take a look at eg. current implementation of Orchard.Security.SecurityFilter to have an idea.
Exception filters are available to handle unhandled exceptions thrown during the execution of the ASP.NET MVC pipeline.
Filtering in ASP.NET MVC http://msdn.microsoft.com/en-us/library/gg416513(v=vs.98).aspx
Checkout ELMAH for system wide error handling.
For the custom page on forgery you could always try and manipulate the Request from within the action filter.
For custom handling of an error message or exception type look at: ASP.NET MVC Custom Error Handling Application_Error Global.asax?

Categories

Resources