Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

462
Views
Response is not being written after Response.End() when request departs from asp:multiview or ajax

I wrote a HttpModule to intercept, evaluate and authorize requests, checking if logged user has appropriate access to the url being requested, in a pretty old legacy system written in ASP.NET 2.0(Web pages, not Web app), whose customer does not want to port to a newer framework. Restrictions have been loaded and cached at login time.

Everything works fine, except when some page contains an <asp:MultiView> component or when there is a button that launch an ajax method. When one of these situations occur, and user doesn't have rights to access that url, an alert box pops up with an "Unknown error" message, that came from a ThreadAbortException thrown by Response.End() method.

The question is: Why does my "Unauthorized" message is being overwritten by "Unknown Error" from the exception, only on these two situations?

Is there a way of doing an Url Authorization system, using database and caching and without cluttering Web.config with roles like those older ASP.NET samples?

// My module init method.
public void Init(HttpApplication context)
{
    context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);

    // PreRequestHandlerExecute is the first stage at ASP.NET Pipeline
    // where we could get a fulfilled Session variable
}

private void context_PreRequestHandlerExecute(object sender, EventArgs e)
{
    HttpApplication application = (HttpApplication)sender;
    HttpContext context = application.Context;

    // additional request filtering/validation/etc.

    LoggedUser user = (LoggedUser)application.Session["user"];

    string path = context.Request.Path;

    // more checks and rules...

    if (!checkUserAuthorization(path, user))
    {
        context.Response.Write("<script>alert('Unauthorized. Contact your manager.');</script>");
        context.Response.Write("<script>window.history.back();</script>");
        context.Response.StatusCode = 403;
        context.Response.End();
    }
}

EDIT: What I've already tried (with no goal):

  • Response.OutputStream.Close();
  • Response.Flush();
  • HttpApplication.CompleteRequest();
over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

it's by design. you must ignore it and add a catch for that exception.

try {
   context.Response.End();
}
catch{}
over 4 years ago · Santiago Trujillo Report

0

Foreword

After a lot of research, finally I got it. Considering ASP.NET 2.0, concerning AJAX operations, the project I'm working uses a Microsoft component called "Atlas", which in turn got renamed to ASP.NET AJAX. At the time this system was written, the developers used the beta ASP.NET AJAX (codename "Atlas") to address all ajax and partial rendering needs.

I needed to dig deeper in source code (thanks to Reflector), to understand and inspect from where does that "Unknown Error" comes.

Inside the Microsoft.Web.Atlas, there is a file named Microsoft.Web.Resources.ScriptLibrary.*.Atlas.js (where * could be Debug or Release) which is rendered at runtime through a WebResource.axd "proxy".

This javascript file have a bug, because it expects to ASP.NET request always return an HTTP 200 (OK) response code, which in my code it's not happening (I'm returning a 403 Forbidden code at my module).

Code

From Microsoft.Web.Resources.ScriptLibrary.*.Atlas.js taken from WebResource.axd:

this._onFormSubmitCompleted = function(sender, eventArgs) {

    var isErrorMode = true;
    var errorNode;
    var delta;
    if (sender.get_statusCode() == 200) {
        delta = sender.get_xml();
        if (delta) {
            errorNode = delta.selectSingleNode("/delta/pageError");
            if (!errorNode) {
                isErrorMode = false;
            }
        }
    }

    if (isErrorMode) {
        if (errorNode) {
            pageErrorMessage = errorNode.attributes.getNamedItem('message').nodeValue;
        }
        else {
            pageErrorMessage = 'Unknown error';
        }
        this._enterErrorMode(pageErrorMessage);
        return;
    }
// Code continues.
}

From this code, we can see that since response code is not an 200 OK, that errorNode variable won't be set, and this if (errorNode) statement will always be false.

In this case, I was left with two options: Always return HTTP 200 and modify all pages that have an <atlas:ScriptManager> with and add an ErrorTemplate tag on each, or supersede that script with one that consider non-HTTP 200 responses, loading it below </form> tag at the Master page.

There is a lot of tutorials on how to do a proper error handling when using ScriptManager and UpdatePanels (an official one here), by subscribing to the AsyncPostBackError event), but this beta version (Atlas) simply don't have this event.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!