I want to pass an identifier to a custom error page in ASP.NET MVC.
I have the web.config set up to redirect to an error page when there is an status 500 error. I don't know how to pass an error id from the application code that throws the exception (also sets HTTP Status of 500) back to the error page that is configured.
It's easy if I just used Status 200 and returned a view from the Error method of the controller and did all the logic in there, however the Status code must be 500, so that's not an acceptable solution.
I also do not and will not use session for this. I'd like to use query string or view data.
Not a duplicate. This is about error handling (status code 500) and exceptions. 404 is about Page Not Found
I don't know a better way to customized information to error page configured in web.config. This is what I normally do when i need an error redirection:
I'll create an error handler action filter:
public class MyErrorHandler: HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
if (filterContext.Exception != null)
{
filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
filterContext.ExceptionHandled = true;
filterContext.Result = new RedirectResult("/error?error_id=123456", true);
return;
}
base.OnException(filterContext);
}
}
Within the Exception filter, you may try to handle differnet error with different error id, or whatever you prefer to alter the exception.
Then apply it onto controller or controler class:
[MyErrorHandler]
public class HomeController : Controller
{
....
}
And you will get a Http status 500 and will be redirected to:
http://<host>/error?error_id=123456
Related
I am refactoring an ASP.NET WEB API solution that uses Odata.
When dealing with errors I would like to provide a custom error payload which is defined in my CustomException class.
The issue is that when I make a bad request the generated response is the ODataException error payload which contains some confidential information that I don't want exposed and also the stack trace.
I need to modify this Odata payload and replace it with my own.
So far what I've tried is to use Exception Filters applied on Controller level and also tried to register an Exception Handler on global level. None of these worked.
Any help would be greatly appreciated.
I was able to resolve it with Exception Filter, I was using the wrong method before:
public class CustomExceptionFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
ErrorContentResponse error = new ErrorContentResponse();
var response = new HttpResponseMessage(actionExecutedContext.Response.StatusCode)
{
Content = new ObjectContent<ErrorContentResponse>(error, new JsonMediaTypeFormatter())
};
actionExecutedContext.Response = response;
}
}
I use the code below to handle all unhandled errors on my controllers:
public abstract class BaseController: Controller
{
protected override void OnException(ExceptionContext filterContext)
{
filterContext.ExceptionHandled = true;
if (IsJsonCall())
filterContext.Result = HandleJsonError(filterContext.Exception);
else
filterContext.Result = HandleError(filterContext.Exception);
}
}
In HandleJsonError function, I return a JSON object with information about the error. In my JavaScript code I detect this info and handle it properly.
Its working fine on localhost, returning a 200 HTTP Code to the client, but in my production environment, it returns the JSON object with the error info, so I can say its running all the code, but its returning a 500 HTTP code instead of 200, which is causing problems when JavaScript tries to recognize the returned content.
Why the codes returned are different event if the content is the same?
I am trying to write my own authorization attribute where I run through some custom checks on any web api method with the CustomAuthorization attribute.
My code is as follows:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class CustomAuthorization : AuthorizationFilterAttribute
{
public override void OnAuthorization(AuthorizationContext context)
{
//// Attempt 1 - 404 error.
//// Doesnt block method with this attribute from executing (not desired behaviour).
//context.HttpContext.Response.StatusCode = 401;
//return;
//// Attempt 2 - 404 result.
//// Code with attribute doesnt execute (desired).
//// Error thrown says: An exception of type 'System.Web.Http.HttpResponseException' occurred in <namespace> but was not handled in user code
//// Additional information: Processing of the HTTP request resulted in an exception. Please see the HTTP response returned by the 'Response' property of this exception for details.
//throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.Unauthorized));
// Attempt 3 - 404 result.
// Code with attribute doesnt execute (desired).
context.Result = new HttpUnauthorizedResult();
}
}
The problem I'm having is that I'm getting a 404 response from the web api instead of an expected 401. What am I doing wrong?
This is asp.net core 1.
Thanks in advance!
It may be because you have authentication setup to redirect to a login page for 401 responses and that login page is not being found (happened to me).
I've implemented a custom IExceptionFilter to handle an exception some users are experiencing with a third party library our application is consuming. When this particular error state occurs, I need to modify the user's cookies (to clear their session state), but what I am finding is that no cookies seem to make it out of the filter. Not sure what's wrong or even how to debug it.
I've modified the functional bits filter to simplify the intent, but here's the gist of the filter. I've ensured that it is the first filter to run on the controller and tested removing the HandleErrorAttribute filter as well to no avail. After the below code runs, "somecookie" is never set on the client.
public class HandleSessionErrorAttribute : FilterAttribute, IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
if (filterContext == null) throw new ArgumentNullException("filterContext");
var exception = filterContext.Exception as HttpException;
if (exception != null && exception.Message.Equals("The session state information is invalid and might be corrupted."))
{
filterContext.HttpContext.Response.Cookies.Add(new HttpCookie("somecookie")
{
Value = DateTime.Now.ToString(),
Expires = DateTime.Now.AddMinutes(5),
});
}
}
}
Okay, figured it out. Two issues were preventing the logic from succeeding:
The HandleErrorAttribute must run before any attribute which modifies the response. Part of the implementation of HandleErrorAttribute is to Clear() the response.
CustomErrors must be On for this to work
The initialization code which worked:
GlobalFilters.Filters.Add(new HandleErrorAttribute() { Order = 0 });
GlobalFilters.Filters.Add(new HandleSessionErrorAttribute() { Order = 1 });
I have a pre-action web api hook that will check ModelState.IsValid. If the ModelState is not valid I do not want to execute the action and just return my message immediately. How exactly do I do this?
public class ValidateModelStateAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext) {
if (!actionContext.ModelState.IsValid)
{
var msg = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState);
// Now What?
}
base.OnActionExecuting(actionContext);
}
}
set the Response.Result. If the result is not null it will not execute the action. the exact syntax is escaping me right now, but it's as simple as
if(actionContext.ModelState.IsValid == false)
{
var response = actionContext.Request.CreateErrorResponse(...);
actionContext.Response = response;
}
Have you actually seen the example on the ASP.NET WebApi page?
Looks very much like what you're trying to achieve and all they do is setting the Response of the Context object:
If model validation fails, this filter returns an HTTP response that contains the validation errors. In that case, the controller action is not invoked.
http://www.asp.net/web-api/overview/formats-and-model-binding/model-validation-in-aspnet-web-api
see: Handling Validation Errors
My guess is that you should throw a HttpResponseException