Who is invoking Error view and why? - c#

I got a MVC4 web application running and functioning properly since almost a year. Lately while reviewing production error logs, I found a lot of mysterious exception entries of same type. I checked logs and found these exceptions occur on both Beta and Production environment but not in local (seems like a hint - see findings 1 below).
There are two subsequent entries:
One is:
Thread Id: 56, Message: Server_Exception - The view 'Error' or its
master was not found or no view engine supports the searched
locations. The following locations were searched:
~/Views/OrganizationUser/Error.cshtml
~/Views/OrganizationUser/Error.vbhtml ~/Views/Shared/Error.cshtml
~/Views/Shared/Error.vbhtml
Second log entry is:
Thread Id: 56, Message: Server_Exception - Stack Trace - at
System.Web.Mvc.ViewResult.FindView(ControllerContext context) at
System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context)
at
System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass25.b__22(IAsyncResult
asyncResult) at
System.Web.Mvc.Controller.<>c__DisplayClass1d.b__18(IAsyncResult
asyncResult) at
System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass4.b__3(IAsyncResult
ar) at System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult
asyncResult) at
System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass4.b__3(IAsyncResult
ar) at
System.Web.Mvc.MvcHandler.<>c__DisplayClass8.b__3(IAsyncResult
asyncResult) at
System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass4.b__3(IAsyncResult
ar) at
System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step,
Boolean& completedSynchronously)
The exception is logged from Application_Error() in global.asax.cs like so:
var ex = Server.GetLastError();
if (ex != null)
{
logger.Log(string.Format("Server_Exception - {0}", ex.Message), LogCategory.Error);
logger.Log(string.Format("Server_Exception - Stack Trace - {0}", ex.StackTrace), LogCategory.Error);
}
And here is the snapshot of DB log messages:
Finding/Analysis:
Since the errors are logged only on remote server, it tells me it has got to do with how MVC handles remote errors? CustomErrors? - I don't have it defined it in web.config. Should I?
But the main question is, what caused the error to happen? And who is looking for view name Error? I know its hard for you to guess it but just checking my luck.
Another finding is the exceptions are logged after user has logged out. In my Login get form, I check isAuthenticated and if user is not authenticated I log a message 'Request not authenticated, showing login form.' and display login form. I can see this message in logged prior to above exception messages. So what's going on on login.cshtml that causes a contact to server which generates an error? I checked, login page and _Layout which has lots of server side code embedded but could not figure out what could cause server to try to load Error page.
I think internally MVC is calling Error page which does not exist in my source code hence these exception. But why 'Error' page? I thought to get advice on what to check in this case. Please advise if you want me to share anything that could help you understand my problem.

I suspect you are using the System.Web.Mvc.HandleErrorAttribute as this attribute will attempt to look for an Error view under certain conditions when an exception is thrown inside a controller action:
The currently executing action is not a child action
The exception has not already been handled or custom errors are enabled
When wrapped in a HttpException, the exception has a 500 HTTP status code
The exception is an instance of System.Exception
When all of the above are true, System.Web.Mvc.HandleErrorAttribute creates a System.Web.Mvc.HandleErrorInfo instance, sets the ExceptionContext.Result property to a ViewResult which by default has the ViewName property set to Error.
Putting all of this together, In one of your controllers, an exception must be being thrown that meets all of the above points, in a controller action that has the [HandleError] attribute applied (maybe it's applied globally), which is attempting to find the Error view and failing to do so.
To know what the original exception is, you could put an Error view into your solution and write out the Exception message of the HandleErrorInfo model instance passed to the view (if the current user has the appropriate access controls).

Related

.Net Core Identity 2 Provider login Cancel leads to unhandled exception

I've added LinkedIn as a provider. I have implemented the login and register with LinkedIn without any issue. In the use case where the user CANCELS from within the provider Pages (either linkedIn login or cancels the authorization of the app) the identity middleware seems to throw an unhandled exception:
An unhandled exception occurred while processing the request.
Exception: user_cancelled_login;Description=The user cancelled LinkedIn login
Unknown location
Exception: An error was encountered while handling the remote login.
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler.HandleRequestAsync()
System.Exception: user_cancelled_login;Description=The user cancelled LinkedIn login
Exception: An error was encountered while handling the remote login.
The provider setup in startup defines the callback:
services.AddAuthentication().AddOAuth("LinkedIn", "LinkedIn", c =>
{
c.ClientId = Configuration["Authentication:LinkedIn:ClientId"];
c.ClientSecret = Configuration["Authentication:LinkedIn:ClientSecret"];
c.Scope.Add("r_basicprofile");
c.Scope.Add("r_emailaddress");
c.CallbackPath = "/signin-linkedin";
....
And As I have said the middleware seems to handled ALL other cases except where the user cancels within the LinkedIn pages. The return URL from LinkedIn looks correct:
https://localhost:44372/signin-linkedin?error=user_cancelled_login&error_description=The+user+cancelled+LinkedIn+login&state=CfDJ8MA7iQUuXmhBuZKmyWK9xeAgBBkQvnhf1akLhCIn9bsajCPUf7Wg22oeZBH9jZOIY3YrchMSWZ4dH7NQ1UngLKEuqgU-IHfBglbgJDtS-wc4Z-6DnW66uR0G1ubvNVqatFJHYv17pgqZT98suVkvKgihcJdbNEw7b1ThkuFbn9-5EcYhQ5ln6ImoTgthT8io1DOcCfc_-nBVfOa93a6CpUJTsZc9w93i70jn5dKKXSLntZe0VyRSA0r0PKc5spu5En-0R1rxiLjsjo4dy89PV3A
But never gets to my ExternalCallback controller method where the other cases like successful login/authorization are handled??
I'm wondering if this is working for anyone else with 3rd part providers?
There's a Github issue that explains what's happening here in more detail, with a bit of information as to why it's happening and even an indication that this won't be "fixed":
Handling the RemoteFailure event is the right thing to do. We should update our docs/samples to show how to handle that event and at least show a more appropriate message to the user. The error page sample could include a link to enabled the user to try logging in again.
Unfortunately it's difficult to implement this event in a very generic way that's also super useful because each remote auth provider has its own behavior for different types of failures.
The workaround for this (as quoted above) is to handle the RemoteFailure event:
services.AddAuthentication().AddOAuth("LinkedIn", "LinkedIn", c => {
// ...
c.Events.OnRemoteFailure = ctx =>
{
// React to the error here. See the notes below.
return Task.CompletedTask;
}
// ...
});
ctx is an instance of RemoteFailureContext, which includes an Exception property describing what went wrong. ctx also contains a HttpContext property, allowing you to perform redirects, etc, in response to such exceptions.
I've found the following to work well for me, based on this and similar to Kirk Larkin's answer. The part that took a little figuring out was where to redirect to, without causing problems for subsequent login attempts.
services.AddAuthentication().AddOAuth("LinkedIn", "LinkedIn", c =>
{
...
c.Events = new OAuthEvents()
{
OnRemoteFailure = (context) =>
{
context.Response.Redirect(context.Properties.GetString("returnUrl"));
context.HandleResponse();
return Task.CompletedTask;
}
};
};

Elmah not logging manual errors

Elmah is working alright catching exceptions that are unhandled. However, in one place I am using the following code to manually log error incase a webapi action causes exception. This error is somehow not displayed in elmah.axd wonder why?
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
Here is something I didn't notice earlier, log in debug window:
Exception thrown: 'System.Web.HttpRequestValidationException' in System.Web.dll
System.Web.HttpRequestValidationException (0x80004005): A potentially dangerous Request.Form value was detected from the client (headers="...8241F for <x+152#mail....").
at System.Web.HttpRequest.ValidateString(String value, String collectionKey, RequestValidationSource requestCollection)
at System.Web.HttpRequest.<>c__DisplayClass280_0.<ValidateHttpValueCollection>b__0(String key, String value)
at System.Web.HttpValueCollection.EnsureKeyValidated(String key)
at System.Web.HttpValueCollection.GetValues(Int32 index)
at System.Collections.Specialized.NameValueCollection.Add(NameValueCollection c)
at Elmah.Error.CopyCollection(NameValueCollection collection)
at Elmah.Error..ctor(Exception e, HttpContext context)
at Elmah.ErrorLogModule.LogException(Exception e, HttpContext context)
More Context to the question:
Basically, I have an action method in webapi which parses and processes incoming email parse from sendgrid. If any type of exception occurs, it is manually logged with ELMAH and Application Insights in Azure. Application Insight logging works while ELMAH is failing with the above error message.

HttpContext.Current.Request.Url.AbsolutePath generate error in global.asax file

I am am using HttpContext.Current.Request.Url.AbsolutePath in global.asax file in one of teh functions to get page related details from database but it fails with following error.
`string _result = Helper.GetPageDetails( HttpContext.Current.Request.Url.AbsolutePath);`
Can i use this HttpContext.Current.Request.Url.AbsolutePath here i need to get the absolutePath of URL and i am getting following error
An exception of type 'System.Web.HttpException' occurred in System.Web.dll but was not handled in user code
Additional information: Request is not available in this context
I catch this in try{} i get following error message details
ex = {"Request is not available in this context"}
This means there is no request associated with the current method call (thread). I am guessing you are calling HttpContext.Current.Request.Url.AbsolutePath from a seperate thread than the one from the request. Without further info thats all i can say
In global.asax you use
Context.Request
as a replacement for
HttpContext.Current.Request

Microsoft ASP.NET Redis Session State throws an exception

When hooking up an ASP.NET website to Azure Redis Cache (but this error also occurs when using a local redis instance) using the Microsoft ASP.NET Redis Session State provider, I get a Null Reference Exception. Why? Google tells me nothing. I have tried using the Russian Redis Session State provider, but that randomly corrupts the session state, so I can't use that either.
This is the stack trace:
[NullReferenceException: Object reference not set to an instance of an object.]
Microsoft.Web.Redis.StackExchangeClientConnection.Eval(String script, String[] keyArgs, Object[] valueArgs) +381
Microsoft.Web.Redis.RedisConnectionWrapper.TryUpdateIfLockIdMatch(Object lockId, ISessionStateItemCollection data, Int32 sessionTimeout) +108
Microsoft.Web.Redis.RedisSessionStateProvider.SetAndReleaseItemExclusive(HttpContext context, String id, SessionStateStoreData item, Object lockId, Boolean newItem) +1280
System.Web.SessionState.SessionStateModule.OnReleaseState(Object source, EventArgs eventArgs) +565
System.Web.SessionState.SessionStateModule.OnEndRequest(Object source, EventArgs eventArgs) +139
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +69
I have no idea where this problem occurs as the stack trace doesn't touch my code, but it occurs on any url hitting my site after I am logged in, yes using forms authentication.
My redis config looks like this:
<sessionState mode="Custom" customProvider="RedisSessionStateStoreProvider">
<providers>
<clear />
<add name="RedisSessionStateStoreProvider" type="Microsoft.Web.Redis.RedisSessionStateProvider, Microsoft.Web.RedisSessionStateProvider, Version=0.4.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
host="*******.redis.cache.windows.net"
throwOnError = "true"
connectionTimeoutInMilliseconds = "5000"
retryTimeoutInMilliseconds = "5000"
operationTimeoutInMilliseconds = "5000"
ssl="true"
accessKey="*******************************"
/>
</providers>
... where I have starred out the access key and service uri.
EDIT: I was happy, and thought I had found the solution when I found a post on MSDN Forums (booh!) that dealt with intermittent null reference exceptions where they warned that a nonexistent key being assigned with with a null value will break everything. I found an instance where I was doing this and fixed it,but that didn't actually do the trick and the same problem remains.
I am using Microsoft.Web.RedisSessionStateProvider 0.4.0.0-Pre-121 that allegedly fixes a similar bug
The problem is that I managed to use Null as a key(!!!). What I thought was a properly named constant (like all the other key names) was in fact a variable that was null.
The effects of this mistake differed considerably, so I will post them here if it helps anybody:
Inserting Null as a key caused both the ASP.NET Universal Providers session state provider and RedisAspNetProviders SessionStateProvider to work until the first deserialization after the fatal value with a null key is inserted, after which they blow up with a HttpException (which is correct, probably, although a slightly more helpful error message could be supplied) or an Out Of Memory exception, when I tried storing a List, which is unexpected.
The Microsoft Redis Session State provider blows up with an NRE directly as the idiotic key is inserted and again, us idiots could probably use a better message to save us time.
I tried to use Azure AppFabric as an alternative before I knew what the error was but it was not responding enough to be tested.

How to get Error code on custom error page

I have a common custom error page for my asp.net website because it's common it is shown on every error I want to found the last error code which was occurred and redirected to my that custom error page so that I can show right message according to the error which was occurred.
Note : solution have to be session based, I don't want any user to show error which was occurred on any other user's system of course.
Do you use IIS or Apache?
For Apache
Configuring Apache to serve customized error pages is extremely easy; there is a section of the httpd.conf file devoted to this. It takes just one directive per error to achieve. If you open the conf file and scroll right down to almost the very bottom of section two, you’ll see the section you need to edit.
By default, these directives are commented out, but all you need to do is un-comment each directive and then change the path to point to your own error page.
ErrorDocument 404 /errordocs/404error.html
For IIS
IIS 6: Edit Website or virtual Directory then Userdefinded Error.
There you can edit all error files and change to a user defined asp.net file.
IIS 7:
Detailed Error Message see:
http://blogs.msdn.com/b/rakkimk/archive/2007/05/25/iis7-how-to-enable-the-detailed-error-messages-for-the-website-while-browsed-from-for-the-client-browsers.aspx
Not good idea what you try to do. You must capture the errors on the code that they occur inside the page, and show the message on that page - stay on page - and if this is possible give the user the opportunity to correct it. If your error gets out of your try/catch and out of control then log it and fix it.
The only error that you can show to your user is the "non found page".
You can get the last error as Exception LastOneError = Server.GetLastError();
And there you can read more about errors: How do I make a "generic error" page in my ASP.NET application so that it handles errors triggered when serving that page itself?
and How to tell if an error captured by my global.asax was displayed on the screen of the user
What I would suggest is extending the UI.Page class and using that class for all your pages.
In that class (I know vb not c# but same principle and easy to convert) use the following code:
Public Class _PageBase
Inherits System.Web.UI.Page
#Region "Page Functions"
Private Sub Page_Error(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Error
Session("error_StackTrace") = Server.GetLastError.StackTrace.ToString
Session("error_Message") = Server.GetLastError.Message.ToString
Session("error_Page") = Request.Url.ToString
Session("error_Source") = Server.GetLastError.Source.ToString
Server.ClearError()
Response.Redirect("~/errors/Error.aspx")
End Sub
#End Region
End Class
This will fire on all pages using that base class, and pass the last 'server' error (which will be the error the user caused), store all the details in session and pass it over to your error page. Then you can do as you wish.

Categories