ELMAH generates errors in quick succession - asp.net

In our intranet there are some clinks with href pointing to my applcation. When any of the links is clicked and browser redirects, ELMAH generates the hundreds of repeating errors below for 10 seconds or so .
System.Web.HttpException: Server cannot set status after HTTP headers have been sent.
Generated: Tue, 13 Dec 2016 17:20:43 GMT
System.Web.HttpException (0x80004005): Server cannot set status after HTTP headers have been sent.
at System.Web.HttpResponse.set_StatusCode(Int32 value)
at System.Web.Mvc.HandleErrorAttribute.OnException(ExceptionContext filterContext)
at System.Web.Mvc.ControllerActionInvoker.InvokeExceptionFilters(ControllerContext controllerContext, IList`1 filters, Exception exception)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult)
My application has the following code in the Application_BeginRequest() and Application_Error() which set statuscode. I am not sure if it has anything to do with it.
protected void Application_BeginRequest(object sender, EventArgs e) {
Response.BufferOutput = true;
//enforce HTTPS
if (!HttpContext.Current.Request.IsLocal && !Request.IsSecureConnection )
{
bool addHttpsAttribute = true;
foreach (Filter filter in GlobalFilters.Filters)
{
if (filter.Instance is RequireHttpsAttribute)
{
addHttpsAttribute = false;
break;
}
}
if (addHttpsAttribute)
GlobalFilters.Filters.Add(new RequireHttpsAttribute());
}
}
protected void Application_Error(object sender, EventArgs e) {
Response.BufferOutput = true;
var httpContext = HttpContext.Current;
var currentRouteData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));
var currentController = " ";
var currentAction = " ";
if (currentRouteData != null) {
if (currentRouteData.Values["controller"] != null && !String.IsNullOrEmpty(currentRouteData.Values["controller"].ToString())) {
currentController = currentRouteData.Values["controller"].ToString();
}
if (currentRouteData.Values["action"] != null && !String.IsNullOrEmpty(currentRouteData.Values["action"].ToString())) {
currentAction = currentRouteData.Values["action"].ToString();
}
}
var ex = Server.GetLastError();
var controller = new myApp.Controllers.ErrorController();
var routeData = new RouteData();
var action = "OtherError";
if (ex is HttpException) {
var httpEx = ex as HttpException;
switch (httpEx.GetHttpCode()) {
case 404:
action = "NotFound";
break;
// others if any
default:
action = "OtherError";
break;
}
}
httpContext.ClearError();
httpContext.Response.Clear();
httpContext.Response.StatusCode = ex is HttpException ? ((HttpException) ex).GetHttpCode() : 500;
httpContext.Response.TrySkipIisCustomErrors = true;
routeData.Values["controller"] = "Error";
routeData.Values["action"] = action;
controller.ViewData.Model = new myApp.Models.HandleErrorInfo(ex, currentController, currentAction);
((IController) controller).Execute(new RequestContext(new HttpContextWrapper(httpContext), routeData));
Context.ApplicationInstance.CompleteRequest();
}

Related

MVC 5 Error The controller for path '/setpassword' was not found

I would to like to know how take control of this error, when I want to redirect to the view error bien the html code isn't rendered , so when I try type this http://localhost:5455/ControllerNotFound, but instead I type http://localhost:5455/Controller/Whatever it's work well.
No rendering ErrorPage when controller NotFound
Erorr page is Showup when action is NotFound
Application Error handler in Global.asax
void Application_Error(object sender, EventArgs e)
{
brMessaging.Util ObjbsUtil = new brMessaging.Util();
brMessaging.LogError ObjbsLogError = new brMessaging.LogError();
try
{
Exception exception = Server.GetLastError();
if (exception != null)
{
Server.ClearError();
var routeData = new RouteData();
routeData.Values.Add("controller", "ErrorHandler");
routeData.Values.Add("action", "Error");
routeData.Values.Add("exception", exception);
if (exception.GetType() == typeof(HttpException))
{
routeData.Values.Add("statusCode", ((HttpException)exception).GetHttpCode());
}
else
{
routeData.Values.Add("statusCode", 500);
var inputData = new Dictionary<string, string>() { {"IP: ", ObjbsUtil.getUserIp(Request) } };
ObjbsLogError.InsertLog(new SystemFramework.Entities.SFException(exception, 0, "Global", "Application_Error", (int)SystemFramework.Enumerator.PortalName.OV_Messaging,
false, Request.Url.ToString(), "Error capturado en el Global.asax", 0, inputData));
}
IController controller = new ErrorHandlerController();
controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
}
}
catch (Exception)
{
}
}

Exception handling in Application_Error, what is sender.Context.Request?

I have Exception-handling code in my Application_Error. I got the code from stackoverflow, its working.
protected void Application_Error(Object sender, EventArgs e)
{
string currentController = "";
string currentAction = "";
HttpContext httpContext = ((MvcApplication)sender).Context;
HttpRequestWrapper httpRequest = new HttpRequestWrapper(httpContext.Request);
RouteData currentRouteData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));
if (!(currentRouteData == null))
{
if (currentRouteData.Values["controller"] != null && !String.IsNullOrEmpty(currentRouteData.Values["controller"].ToString()))
{
currentController = currentRouteData.Values["controller"].ToString();
}
if (currentRouteData.Values["action"] != null && !String.IsNullOrEmpty(currentRouteData.Values["action"].ToString()))
{
currentAction = currentRouteData.Values["action"].ToString();
}
}
var exception = Server.GetLastError();
if (exception == null)
return;
// Clear the error
Server.ClearError();
Models.Exception ex = new Models.Exception();
ex.ErrorMessage = exception.Message;
ex.ErrorUrl = String.Format("{0}/{1}", currentController, currentAction);
FreelancerDB.SaveExceptions(ex);
Response.Redirect("~/WebsiteAccess/SystemError");
}
The problem is that I dont understand what is happening in these 2 linies:
HttpContext httpContext = ((MvcApplication)sender).Context;
HttpRequestWrapper httpRequest = new HttpRequestWrapper(httpContext.Request);
Can anyone explain what is happening here?
Nothing is happening there, the httpRequest variable isn't used afterwards.
It does give you a reference to the request during which the exception was generated, might you need it.

HttpModule Web Api

I'm trying to get an auth basic on my web api. I've written a simple HttpModule to check it
public class BasicAuth : IHttpModule
{
SqlConnection con = new SqlConnection(WebConfigurationManager.ConnectionStrings["Connection"].ConnectionString);
private const string Realm = "MyRealm";
public void Init(HttpApplication context)
{
// Register event handlers
context.AuthorizeRequest += new EventHandler(OnApplicationAuthenticateRequest);
context.EndRequest += new EventHandler(OnApplicationEndRequest);
}
private static void SetPrincipal(IPrincipal principal)
{
Thread.CurrentPrincipal = principal;
if (HttpContext.Current != null)
{
HttpContext.Current.User = principal;
}
}
private bool CheckPassword(string username, string password)
{
var parameters = new DynamicParameters();
parameters.Add("#UserName", username);
parameters.Add("#Password", password);
con.Open();
try
{
var query = //query to db to check username and password
return query.Count() == 1 ? true : false;
}
catch
{
return false;
}
finally
{
con.Close();
}
}
private bool AuthenticateUser(string credentials)
{
try
{
var encoding = Encoding.GetEncoding("iso-8859-1");
credentials = encoding.GetString(Convert.FromBase64String(credentials));
int separator = credentials.IndexOf(':');
string name = credentials.Substring(0, separator);
string password = credentials.Substring(separator + 1);
if (CheckPassword(name, password))
{
var identity = new GenericIdentity(name);
SetPrincipal(new GenericPrincipal(identity, null));
return true;
}
else
{
return false;
}
}
catch
{
return false;
}
}
private void OnApplicationAuthenticateRequest(object sender, EventArgs e)
{
var authHeader = request.Headers["Authorization"];
if (authHeader != null)
{
var authHeaderVal = AuthenticationHeaderValue.Parse(authHeader);
// RFC 2617 sec 1.2, "scheme" name is case-insensitive
if (authHeaderVal.Scheme.Equals("basic",
StringComparison.OrdinalIgnoreCase) &&
authHeaderVal.Parameter != null)
{
if (AuthenticateUser(authHeaderVal.Parameter))
{
//user is authenticated
}
else
{
HttpContext.Current.Response.StatusCode = 401;
}
}
else
{
HttpContext.Current.Response.StatusCode = 401;
}
}
catch
{
HttpContext.Current.Response.StatusCode = 401;
}
}
private static void OnApplicationEndRequest(object sender, EventArgs e)
{
var response = HttpContext.Current.Response;
if (response.StatusCode == 401)
{
response.Headers.Add("WWW-Authenticate",
string.Format("Basic realm=\"{0}\"", Realm));
}
}
public void Dispose()
{
}
}
well, this code works pretty well, except the fact it asks for basic auth even on controller I don't put the [Authorize] tag on. And when it occurs, it gives the right data back.
Let me explain:
My HistoryController has [Authorize] attribute, to make a POST request I have to send Header auth to get data, if I don't do it, I receive 401 status code and a custom error.
My HomeController doesn't have [Authorize] attribute, if i make a get request on my homepage, the browser popups the authentication request, but if I hit Cancel it shows my home page. (The page is sent back with 401 error, checked with fiddler).
What am I doing wrong?

Controller.Execute rendering as text file with no content type

When a 404 or 500 happens the page shows as a text file. The content type is empty in the response. How can I fix this so the content renders as a "text/html" page.
protected void Application_Error()
{
var context = new HttpContextWrapper(Context);
if (!context.Request.IsAjaxRequest())
{
var unhandledException = Server.GetLastError();
var httpException = unhandledException as HttpException;
if (httpException == null)
{
var innerException = unhandledException.InnerException;
httpException = innerException as HttpException;
}
var routeData = new RouteData();
routeData.Values.Add("controller", MVC.Errors.Name);
if (httpException != null)
{
var httpCode = httpException.GetHttpCode();
switch (httpCode)
{
case (int)HttpStatusCode.NotFound:
routeData.Values.Add("action", "PageNotFound");
Server.ClearError();
IController pageNotFoundController = new ErrorsController();
pageNotFoundController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
break;
}
}
else
{
routeData.Values.Add("action", "Error");
Server.ClearError();
IController errorController = new ErrorsController();
errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
}
}
}
I added this and it fixed it.
if (!context.Request.IsAjaxRequest())
{
context.Response.ContentType = "text/html";

ASP.NET: How to persist Page State accross Pages?

I need a way to save and load the Page State in a persistent manner (Session). The Project i need this for is an Intranet Web Application which has several Configuration Pages and some of them need a Confirmation if they are about to be saved. The Confirmation Page has to be a seperate Page. The use of JavaScript is not possible due to limitations i am bound to. This is what i could come up with so far:
ConfirmationRequest:
[Serializable]
public class ConfirmationRequest
{
private Uri _url;
public Uri Url
{ get { return _url; } }
private byte[] _data;
public byte[] Data
{ get { return _data; } }
public ConfirmationRequest(Uri url, byte[] data)
{
_url = url;
_data = data;
}
}
ConfirmationResponse:
[Serializable]
public class ConfirmationResponse
{
private ConfirmationRequest _request;
public ConfirmationRequest Request
{ get { return _request; } }
private ConfirmationResult _result = ConfirmationResult.None;
public ConfirmationResult Result
{ get { return _result; } }
public ConfirmationResponse(ConfirmationRequest request, ConfirmationResult result)
{
_request = request;
_result = result;
}
}
public enum ConfirmationResult { Denied = -1, None = 0, Granted = 1 }
Confirmation.aspx:
protected void Page_Load(object sender, EventArgs e)
{
if (Request.UrlReferrer != null)
{
string key = "Confirmation:" + Request.UrlReferrer.PathAndQuery;
if (Session[key] != null)
{
ConfirmationRequest confirmationRequest = Session[key] as ConfirmationRequest;
if (confirmationRequest != null)
{
Session[key] = new ConfirmationResponse(confirmationRequest, ConfirmationResult.Granted);
Response.Redirect(confirmationRequest.Url.PathAndQuery, false);
}
}
}
}
PageToConfirm.aspx:
private bool _confirmationRequired = false;
protected void btnSave_Click(object sender, EventArgs e)
{
_confirmationRequired = true;
Response.Redirect("Confirmation.aspx", false);
}
protected override void SavePageStateToPersistenceMedium(object state)
{
if (_confirmationRequired)
{
using (MemoryStream stream = new MemoryStream())
{
LosFormatter formatter = new LosFormatter();
formatter.Serialize(stream, state);
stream.Flush();
Session["Confirmation:" + Request.UrlReferrer.PathAndQuery] = new ConfirmationRequest(Request.UrlReferrer, stream.ToArray());
}
}
base.SavePageStateToPersistenceMedium(state);
}
I can't seem to find a way to load the Page State after being redirected from the Confirmation.aspx to the PageToConfirm.aspx, can anyone help me out on this one?
If you mean view state, try using Server.Transfer instead of Response.Redirect.
If you set the preserveForm parameter
to true, the target page will be able
to access the view state of the
previous page by using the
PreviousPage property.
use this code this works fine form me
public class BasePage
{
protected override PageStatePersister PageStatePersister
{
get
{
return new SessionPageStatePersister(this);
}
}
protected void Page_PreRender(object sender, EventArgs e)
{
//Save the last search and if there is no new search parameter
//Load the old viewstate
try
{ //Define name of the pages for u wanted to maintain page state.
List<string> pageList = new List<string> { "Page1", "Page2"
};
bool IsPageAvailbleInList = false;
foreach (string page in pageList)
{
if (this.Title.Equals(page))
{
IsPageAvailbleInList = true;
break;
}
}
if (!IsPostBack && Session[this + "State"] != null)
{
if (IsPageAvailbleInList)
{
NameValueCollection formValues = (NameValueCollection)Session[this + "State"];
String[] keysArray = formValues.AllKeys;
if (keysArray.Length > 0)
{
for (int i = 0; i < keysArray.Length; i++)
{
Control currentControl = new Control();
currentControl = Page.FindControl(keysArray[i]);
if (currentControl != null)
{
if (currentControl.GetType() == typeof(System.Web.UI.WebControls.TextBox))
((TextBox)currentControl).Text = formValues[keysArray[i]];
else if (currentControl.GetType() == typeof(System.Web.UI.WebControls.DropDownList))
((DropDownList)currentControl).SelectedValue = formValues[keysArray[i]].Trim();
else if (currentControl.GetType() == typeof(System.Web.UI.WebControls.CheckBox))
{
if (formValues[keysArray[i]].Equals("on"))
((CheckBox)currentControl).Checked = true;
}
}
}
}
}
}
if (Page.IsPostBack && IsPageAvailbleInList)
{
Session[this + "State"] = Request.Form;
}
}
catch (Exception ex)
{
LogHelper.PrintError(string.Format("Error occured while loading {0}", this), ex);
Master.ShowMessageBox(enMessageType.Error, ErrorMessage.GENERIC_MESSAGE);
}
}
}

Resources