No response is written after Response.End () when request is sent from asp: multiview or ajax

I wrote an HttpModule to intercept, evaluate and authorize requests, checking if the logged in user has appropriate access to the requested url, on a fairly old legacy system written in ASP.NET 2.0 (web pages, not a web application), the client fails wants to transfer to a newer structure. The limits were loaded and cached at login time.

Everything works fine except when some page contains a component <asp:MultiView>

or when there is a button that triggers an ajax method. When one of these situations occurs and the user does not have permission to access that URL, an alert box appears with an "Unknown error" message that comes from the method ThreadAbortException

generated by the method Response.End()

.

Question: Why is my "unauthorized" message being overwritten by the "Unknown error" from the exception, only in these two situations?

Is there a way to make a Url authorization system using database and caching and without being cluttered Web.config

with roles like those old 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 (no target):

  • Response.OutputStream.Close();

  • Response.Flush();

  • HttpApplication.CompleteRequest();

+3


source to share


2 answers


Foreword

After a lot of research, I finally got it. Considering ASP.NET 2.0 regarding AJAX operations, the project I work on uses a Microsoft component called "Atlas", which in turn has been renamed ASP.NET AJAX . At the time this system was written, the developers were using the ASP.NET AJAX beta (codenamed "Atlas") to meet all the ajax and partial rendering needs.

I needed to dig deeper into the source code (thanks to Reflector) to understand and verify where this "Unknown error" is coming from.

Inside Microsoft.Web.Atlas there is a file named Microsoft.Web.Resources.ScriptLibrary.*.Atlas.js

(where *

may be Debug

or Release

) that is displayed at runtime through the proxy WebResource.axd

.

There is an error in this javascript file as it expects an ASP.NET request to always return a response code HTTP 200 (OK)

which is not happening in my code (I am returning the code 403 Forbidden

in 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 you can see that since the response code is not 200 OK

, the variable errorNode

will not be set and this operator if (errorNode)

will always be false

.

In this case, I was left with two options: Always revert HTTP 200

and modify all pages from <atlas:ScriptManager>

and add a tag ErrorTemplate

on each one, or replace the script with the one that counts non-HTTP 200

by loading it below the tag </form>

on the homepage.

There are many tutorials on how to handle errors correctly when using ScriptManager and UpdatePanels (official here ), by subscribing to an event AsyncPostBackError

), but this beta (Atlas) just doesn't have this event.

0


source


it's by design. you should ignore it and add catch for this exception.



try {
   context.Response.End();
}
catch{}

      

0


source







All Articles