7
\$\begingroup\$

The situation is that its not always possible to play with the web.config or have access to IIS, that being said I had to come up with a way to catch all 404s in a .NET application, for aspx page extensions its fairly easily and the web is full of ideas... but for non aspx extensions I did the following, looking for advice, is this a good way? are their scenarios where it might fail? does it measure well in performance? thanks for advice

After checking my web.sitemap links and make my rewrites, the "else" block contains the following

string s = context.Server.MapPath(context.Request.AppRelativeCurrentExecutionFilePath);
if (!System.IO.File.Exists(s)){
    throw new HttpException(404, "Page not found");
}

and of course, the rest is handled by the application error handler notice that all css, js, jpegs and other file types go through this check

edit: two problems seem to be persistent with regular error catch, html and friendly urls, they never seem to fire 404s (guessing there other file types, depends on isapi filters)

\$\endgroup\$
6
  • \$\begingroup\$ Where is this code? Somewhere in Global.asax? \$\endgroup\$
    – Andrew Barber
    Dec 2, 2011 at 18:10
  • \$\begingroup\$ yes, in a custom HttpModule class, on application.BeginRequest += (new EventHandler(this.Application_BeginRequest)); \$\endgroup\$
    – Ayyash
    Dec 2, 2011 at 19:35
  • \$\begingroup\$ im getting a lot of "why whould this happen in the first place" when my question is about the efficiency of the solution i proposed, i really can't pinpoint the reason why i spent four weeks trying to figure out a fix except: got frustrated with undependable 404 catches that needed too much time and effort to try on public hosting, but can i get u guys to focus on validating the quality of the fix proposed? \$\endgroup\$
    – Ayyash
    Dec 14, 2011 at 21:25
  • \$\begingroup\$ moving my question from stackoverflow to code review has KILLED it :( \$\endgroup\$
    – Ayyash
    Dec 21, 2011 at 13:21
  • \$\begingroup\$ I demanded to move it here... as this one is not question but arguments. Question would have answer. \$\endgroup\$
    – dipak
    Dec 26, 2011 at 0:08

3 Answers 3

1
\$\begingroup\$

404 is an error and normally should be captured with a relative event. Since you have a custom module you can do the following in the module:

public void Init(HttpApplication context)
{
    // your code
    context.Error +=new EventHandler(OnError);
}

private void OnError(object sender, EventArgs e)
{
    int ec = ((HttpException)HttpContext.Current.Error).GetHttpCode();
    if (ec == 404)
    {
        // do whatever you want
    }
}

If you follow this path you will have the advantage to control all error codes your way and avoid early 404 drops in case you change your rewriting policy or logic.

\$\endgroup\$
1
  • \$\begingroup\$ that is already in place, but it still does not fire when a non ASPX page is requested, if HTML or jpeg or anything, it will fire the regular IIS ugly 404 page, the solution to that was to make a wild-card ISAPI on IIS which affects the configuration, but the solution im proposing here works fine for me, im just worried of going the wrong path of checking file existence of every resource used on web... \$\endgroup\$
    – Ayyash
    Dec 12, 2011 at 7:58
0
\$\begingroup\$

An answer provided to me recently by GregB might be exactly what you need:

What about using an HTTP Handler mapped to all requests?

You'll need to add a wildcard application mapping as detailed here and correctly configure your HTTP Handler.

\$\endgroup\$
10
  • 1
    \$\begingroup\$ Ayyash is specifically asking about doing this without requiring use of web.config, so an answer that requires editing web.config isn't helpful. -1 \$\endgroup\$
    – Andrew Barber
    Dec 2, 2011 at 17:47
  • \$\begingroup\$ I think you just added requirements to the question that don't exist. "Without playing with IIS configuration" isn't the same as saying "don't touch web.config". As well, adding a wildcard mapping will require a change to IIS configuration I'm aware, but since it's a do-once-and-youre-done thing, I still don't feel it's "playing with IIS configuration" \$\endgroup\$
    – Dracorat
    Dec 2, 2011 at 17:52
  • \$\begingroup\$ "its not always possible to play with the web.config" seems pretty clear to me. The rest of the context of the question reinforces my assumption; He clearly wants a code-only solution, and your solution is clearly configuration. \$\endgroup\$
    – Andrew Barber
    Dec 2, 2011 at 17:54
  • 2
    \$\begingroup\$ Andrew guessed right, I cannot really deal with IIS at all, and sometimes the host does not accept certain web.config changes, that's why i am looking for a code-only solution, but thank you Dracorat \$\endgroup\$
    – Ayyash
    Dec 2, 2011 at 19:44
  • 1
    \$\begingroup\$ @ANeves There is a lot of history that's larger than this question and these comments. So instead of diving in to all that, I'll just say that I agree with you. I don't mind -1s when they're constructive. As this is more than a couple weeks old at this point, I'm just going to let it all rest too. I really do hope the question gets an answer that suits the asker. \$\endgroup\$
    – Dracorat
    Dec 12, 2011 at 15:46
0
\$\begingroup\$

So here is my attempt to provide solution.

Application Domain restarts every time when we modify web.config. So I have modified web.config programmatically, But I believe you have write access to web.config file otherwise do not read further.

    void Application_Start(object sender, EventArgs e)
    {
        // Get the current configuration file.
        Configuration configuration = WebConfigurationManager.OpenWebConfiguration("~");
        CustomErrorsSection customErrorsSection = (CustomErrorsSection)configuration.GetSection("system.web/customErrors");

        CustomError error = customErrorsSection.Errors.Get("404");
        if (error==null)
        {
            // set as required
            customErrorsSection.Mode = CustomErrorsMode.On;

            error = new CustomError(404, "NotFoundPage.aspx");
            customErrorsSection.Errors.Add(error);
            configuration.Save(ConfigurationSaveMode.Modified);
        }
    }

While you modify Web.Config you need to put proper conditions as required else you might end up infinite loops.

Be Careful there

Hope this will help.

\$\endgroup\$
8
  • \$\begingroup\$ this method does not take care of non aspx pages, and no, the thing about configuration files on public hosts isnt write access, its more of overriding some sections is not allowed \$\endgroup\$
    – Ayyash
    Dec 11, 2011 at 13:33
  • \$\begingroup\$ "this method does not take care of non aspx pages" have you tried it with non aspx pages? I have tried it before posting it and it is working. If you have no access to Web.config thats fine, But your AppPOOL or process under which your app runs should have access. \$\endgroup\$
    – Dipak Goswami
    Dec 11, 2011 at 18:28
  • \$\begingroup\$ And you never mentioned that overriding of sections is not allowed. I believe you wasting important time of people as this not possible to Deplay web site without having access to Web.config at first place. \$\endgroup\$
    – Dipak Goswami
    Dec 11, 2011 at 18:34
  • \$\begingroup\$ not only do i have no access to some sections, but sometimes working with a big corp with sub sites does not give much freedom of dealing with it, i guess im asking because im fed up with having to handle the iis on a web-based iis interface (its just a simple almost free host) and wait for 30 minutes to see something... i need a fix that i can rely on immidiately \$\endgroup\$
    – Ayyash
    Dec 12, 2011 at 8:05
  • 1
    \$\begingroup\$ that exactly what I'm trying to figure out, how this is possible to have not access to web.config? How you deploy stuff on server without access? How you deploy your Code? "its not always possible to play with the web.config" can be true? I'm starving to hear the solution.... \$\endgroup\$
    – dipak
    Dec 12, 2011 at 11:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.