httpErrors - Redirect 403 to HTML file - How to? - redirect

I am trying to redirect to a html file when I receive a 403 error in my application. This is handled by IIS, so i have added this into my web config:
<httpErrors errorMode="Custom" >
<remove statusCode="403"/>
<error statusCode="403" responseMode="File" path="/500.html"/>
</httpErrors>
Which gives me this error:
You do not have permission to view this directory or page.
However if I change the response mode to ExecuteURL it will redirect to the page. But it will show a http status code of 200, whereas file will keep the 403 error. I just can't get it to redirect to this file.
Can anyone help me fix this issue?

According to the description of the system.webserver/httperrors/error configuration node (https://www.iis.net/configreference/system.webserver/httperrors/error), setting the responseMode attribute to File requires provding an absolute Windows path to the error page. As in the example below:
<configuration>
<system.webServer>
<httpErrors errorMode="DetailedLocalOnly" defaultResponseMode="File" >
<remove statusCode="500" />
<error statusCode="500"
prefixLanguageFilePath="C:\Contoso\Content\errors"
path="500.htm" />
</httpErrors>
</system.webServer>
</configuration>

Related

IIS 10 returning 200 for 404 page

I have the following server configuration on my staging and production server for a custom 404 page, and I am performing some operations based on 404 URLs on my custom 404 page. And getting status as 404 for a non-existing page is necessary for the operation I am performing on my custom 404 page.
<httpErrors>
<remove statusCode="403" subStatusCode="-1" />
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" prefixLanguageFilePath="" path="/404.php" responseMode="ExecuteURL" />
</httpErrors>
With the above configuration on the production server, I am getting 200 status code for a 404 page but the same is working fine on my stagging server. The only difference between my stagging and production server is that staging is on IIS 8.5 and production is on IIS 10. I m not able to get what missing to achieve the same on the IIS10 production server.

Having trouble with web.config redirect; 500 internal server error

I've created a new website and some old links don't work so I want to redirect those links to my new homepage with anchor tags. I have tried so many code snippets but nothing is working. Can anyone see what I've done wrong (I'm not a programmer) thanks! -
I just get:
500 - Internal server error. There is a problem with the resource you
are looking for, and it cannot be displayed.
Here is my code:
<location path="page_contact.html">
<system.webServer>
<httpRedirect enabled="true" destination="http://www.mywebsite.com/index.html#contact" httpResponseStatus="Permanent" />
</system.webServer>
</location>
<location path="portfolio.html">
<system.webServer>
<httpRedirect enabled="true" destination="http://www.mywebsite.com/index.html#portfolio" httpResponseStatus="Permanent" />
</system.webServer>
</location>

fontawsome-webfont.woff not found error in deployed Orchard CMS website

I use Orchard CMS 1.10.1. In the layout.cshtml file of current theme, I added these:
Style.Require("bootstrap");
Style.Require("fontawesome");
and the web.config file of Orchard.Web contains these:
<staticContent>
<remove fileExtension=".svg" />
<mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
<remove fileExtension=".woff" />
<mimeMap fileExtension=".woff" mimeType="application/font-woff" />
<remove fileExtension=".woff2" />
<mimeMap fileExtension=".woff2" mimeType="font/woff2" />
</staticContent>
In my machine there was no problem but when I deployed this on server I get these errors in browser console:
Get http://x.com/Themes/y/fonts/fontawesome-webfont.woff2?v=4.3.0
GET http://x.com/Themes/y/fonts/fontawesome-webfont.woff?v=4.3.0
GET http://x.com/Themes/y/fonts/fontawesome-webfont.ttf?v=4.3.0 404 (Not Found)
What might cause this problem?
You need a <clear/> as first element inside static handlers before first <remove..../> and add a ttf handler as well

IIS7.5 Gives 500 Internal Server Error when trying to use DELETE verb

I am trying to issue a DELETE to an IIS7.5 resource:
DELETE http://198.252.206.16:48251/Test/foo.ashx HTTP/1.1
Accept: */*
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
Host: 198.252.206.16:48251
Content-Length: 0
Connection: Keep-Alive
Pragma: no-cache
And the server responds with:
HTTP/1.1 500 Internal Server Error
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Wed, 12 Feb 2014 01:01:30 GMT
Content-Length: 0
The damnedest thing is:
it works fine inside Cassini (the .NET based web-server used by Visual Studio)
nothing is logged in the Windows Event log
Custom errors are off in the site's web.config
No verbs are being filtered (or all verbs are being included)
WebDAV module is disabled
LiveStreamingHandler module is not installed
Why does IIS not work?
Steps to reproduce
Create a web-site with the generic handler:
Foo.ashx
<%# WebHandler Language="C#" Class="Foo" %>
using System;
using System.Web;
public class Foo : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
}
public bool IsReusable { get { return false; } }
}
and then issue a DELETE verb to the resource. You can use Fiddler to compose the request, if you like:
What about other verbs you ask?
You didn't try to reproduce it, did you? Well, i'll show you the results here:
GET: works
POST: works
PUT: works
HEAD: works
TRACE: 501 Not Implemented
DELETE: 500 Internal Server Error
SEARCH: 405 Method Not Allowed
PROPFIND: 500 Internal Server Error
PROPPATCH: 500 Internal Server Error
PATCH: 405 Method Not Allowed
MKCOL: 405 Method Not Allowed
COPY: 500 Internal Server Error
MOVE: 500 Internal Server Error
LOCK: 500 Internal Server Error
UNLOCK: 500 Internal Server Error
OPTIONS: 200 OK
IISUCKSFOO 405 Method Not Allowed
And just to be anal retentive, a snippet of the relevant portions from web.config:
<?xml version="1.0"?>
<configuration>
<system.web>
<httpRuntime/>
<!-- IISFIX: By default IIS hides errors-->
<customErrors mode="Off"/>
<!-- IISFIX: By default IIS ignores the browser's culture -->
<globalization culture="auto" uiCulture="auto"/>
<!--Doesn't work for ASP.net web-sites, only ASP.net applications-->
<trace enabled="true" requestLimit="40" localOnly="false" />
<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="System.DirectoryServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="System.DirectoryServices.AccountManagement, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Data.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
</assemblies>
</compilation>
</system.web>
<!-- ASP.net web-sites do not support WebPageTraceListener (only ASP.net web-applications)
So this section doesn't work; and does nothing.
But if Microsoft ever fixes IIS, we will start working automagically. -->
<system.diagnostics>
<trace>
<listeners>
<add name="WebPageTraceListener" type="System.Web.WebPageTraceListener, System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
</listeners>
</trace>
</system.diagnostics>
<system.webServer>
<!-- IISFIX: By default IIS ignores custom error pages -->
<httpErrors existingResponse="PassThrough"/>
<defaultDocument>
<files>
<clear/>
<add value="Default.htm"/>
<add value="Default.asp"/>
<add value="index.htm"/>
<add value="index.html"/>
<add value="iisstart.htm"/>
<add value="default.aspx"/>
<add value="test.htm"/>
</files>
</defaultDocument>
<!--IISFIX: By default IIS doesn't understand HTTP protocol-->
<security>
<requestFiltering>
<verbs>
<add verb="OPTIONS" allowed="true" />
<add verb="GET" allowed="true" />
<add verb="HEAD" allowed="true" />
<add verb="POST" allowed="true" />
<add verb="PUT" allowed="true" />
<add verb="TRACE" allowed="true" />
<add verb="DELETE" allowed="true" />
</verbs>
</requestFiltering>
</security>
<modules runAllManagedModulesForAllRequests="true">
<!--IISFIX: Whatever this is, it causes 405 Method Not Allowed errors on IIS when using PUT. (Microsoft's broken by defult)-->
<remove name="WebDAVModule"/>
</modules>
</system.webServer>
</configuration>
Edit - forgot the screenshot of verbs:
The question was sufficiently asked in the title. The rest of the post is just filler to make it look like it shows research effort; which means you have to upvote it - the tooltip on the upvote arrow says so!
The answer turns out to be caused by more of Microsoft's Broken by default policy.
Rather than acting as a web-server, accepting requests and handling them, ASP.net by default decides to ignore the majority of requests - because it thinks the user shouldn't be doing them.
The solution is to rip everything related to ASP.net out of IIS, and then re-add it correctly:
web.config
<?xml version="1.0"?>
<configuration>
<modules runAllManagedModulesForAllRequests="true">
<!--IISFIX: Whatever this is, it causes 405 Method Not Allowed errors on IIS when using PUT. (Microsoft's broken by defult)-->
<remove name="WebDAVModule"/>
</modules>
<handlers>
<!--IISFIX: ASP.net is broken by default. By default they will not accept verbs from the client.
First we have to rip out everything related to ASP.net-->
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit"/>
<remove name="ExtensionlessUrlHandler-Integrated-4.0"/>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit"/>
<remove name="SimpleHandlerFactory-ISAPI-2.0-64"/>
<remove name="SimpleHandlerFactory-ISAPI-2.0"/>
<remove name="SimpleHandlerFactory-Integrated"/>
<remove name="SimpleHandlerFactory-Integrated-4.0"/>
<remove name="SimpleHandlerFactory-ISAPI-4.0_64bit"/>
<remove name="SimpleHandlerFactory-ISAPI-4.0_32bit"/>
<!-- IISFIX: Now that we're ripped out everything related to ASP.net, put them back correctly.-->
<add name="SimpleHandlerFactory-ISAPI-4.0_32bit" path="*.ashx" verb="*" modules="IsapiModule" scriptProcessor="C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="Script" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0"/>
<add name="SimpleHandlerFactory-ISAPI-4.0_64bit" path="*.ashx" verb="*" modules="IsapiModule" scriptProcessor="C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="Script" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0"/>
<add name="SimpleHandlerFactory-Integrated-4.0" path="*.ashx" verb="*" type="System.Web.UI.SimpleHandlerFactory" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0"/>
<add name="SimpleHandlerFactory-Integrated" path="*.ashx" verb="*" type="System.Web.UI.SimpleHandlerFactory" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode"/>
<add name="SimpleHandlerFactory-ISAPI-2.0" path="*.ashx" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="Script" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0"/>
<add name="SimpleHandlerFactory-ISAPI-2.0-64" path="*.ashx" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="Script" preCondition="classicMode,runtimeVersionv2.0,bitness64" responseBufferLimit="0"/>
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="*" modules="IsapiModule" scriptProcessor="C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="Script" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0"/>
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0"/>
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="*" modules="IsapiModule" scriptProcessor="C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="Script" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0"/>
<!--IISFIX: WebDAV is also buggy, and interferes with client requests-->
<remove name="WebDAV"/>
</handlers>
</system.webServer>
</configuration>
The problem now is that the web-site will not work on anyone else's machine; there are now hard-coded paths to files in web.config.
Why, oh why, couldn't Microsoft just do things right.
For completeness
For my own reference, here are the other things that i need to add to web.config every time because the defaults are wrong:
<system.web>
<httpRuntime/>
<!-- IISFIX: By default IIS hides errors-->
<customErrors mode="Off"/>
<!-- IISFIX: By default IIS ignores the browser's culture -->
<globalization culture="auto" uiCulture="auto"/>
</system.web>
<!-- ASP.net web-sites do not support WebPageTraceListener (only ASP.net web-applications)
So this section doesn't work; and does nothing.
But if Microsoft ever fixes IIS, we will start working automagically. -->
<system.diagnostics>
<trace>
<listeners>
<add name="WebPageTraceListener" type="System.Web.WebPageTraceListener, System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
</listeners>
</trace>
</system.diagnostics>
<system.webServer>
<!-- IISFIX: By default IIS ignores custom error pages -->
<httpErrors existingResponse="PassThrough"/>
</system.webServer>
I found that removing webDav references from handlers and modules in the above solution still resulted in IIS 7.5, IIS 7 Windows server 2008 r2 (I never tested IIS 8) for http methods PUT, DELETE
HTTP Error 500.21 - Internal Server Error
Handler "ExtensionlessUrlHandler-Integrated-4.0" has a bad module "ManagedPipelineHandler"
This server error is misleading and also given for improper .net installations where a handler is missing, and can be fixed by re-installing .Net, but that's probably not a solution, if it only affects PUT or DELETE requests to the extension-less route handler (GET, POST, and OPTIONS were fine). I read so many posts about enabling put and delete methods in MVC and Web api that seemed to claim this was a fix so I tried it anyway several times, restarted IIS etc, no change in the error.
the problem did not no go away until I added runManagedModulesForWebDavRequests="true" attribute to the modules element.
< modules runAllManagedModulesForAllRequests="true" runManagedModulesForWebDavRequests="true" >
http://www.iis.net/configreference/system.webserver/modules
By default runManagedModulesForWebDavRequests ="false" which means any webDav request is routed to WebDav. So far as I can deduce, A webdav request is all http PUT or DELETE requests as far as IIS is concerned, even if you have removed the webdav handler from web config and your request body doesn't conform to a webdav request. It's possible that uninstalling webDav might also correct the problem, but I never tried that; I have other sites running on the same server that depend on it.
I found the answer here:
ASP.NET Core with IIS - HTTP Verb Not Allowed
This is the web.config
<configuration>
<!-- To customize the asp.net core module uncomment and edit the following section.
For more info see https://go.microsoft.com/fwlink/?linkid=838655 -->
<system.webServer>
<modules>
<remove name="WebDAVModule" />
</modules>
<handlers>
<remove name="aspNetCore" />
<remove name="WebDAV" />
<!-- I removed the following handlers too, but these
can probably be ignored for most installations -->
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="aspNetCore"
path="*"
verb="*"
modules="AspNetCoreModule"
resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="%LAUNCHER_PATH%"
arguments="%LAUNCHER_ARGS%"
stdoutLogEnabled="false"
stdoutLogFile=".\logs\stdout" />
</system.webServer>
Something to note on this in the future is when you code gets deployed to anything not local, that you change possible hard coded credentials to you generic access accounts. I had this exact issue for a full day and a half and saw that a DELETE .net request that worked with an LDAP was using a hard coded employee ID of a former employee as the UserPrincipalName. It worked fine until his ID finally got removed from our system then everything went bad. Again after a day and half we found the hard coded credentials used for testing purposes. Simple example to illustrate the different things that have to be accounted for on different testing environments.

What is the difference between customErrors and httpErrors?

What is the difference between the customErrors and httpErrors sections of the web.config file in ASP.NET MVC applications?
What are the guidelines for using each section?
*Updated April 2016
The customErrors attribute is used when the .net code is throwing an exception (404, 403, 500 etc) and the httpErrors attribute is used when IIS itself is throwing an exception.
/myfakeextensionslessurl --> httpErrors 404
/myfakeaspsx.aspx --> customErrors 404
/myfakeimage.jpg --> httpErrors 404
/throw500.apx --> customErrors 500
/throw500 --> customErrors 500
There are a lot of pitfalls trying to configure this correctly. So if you are looking for a quick example, the best 2 options you have are:
Example 1: Using html pages
<system.web>
<customErrors mode="RemoteOnly" defaultRedirect="/Error500.html" redirectMode="ResponseRewrite">
<error statusCode="403" redirect="/Error403.html" />
<error statusCode="404" redirect="/Error404.html" />
<error statusCode="500" redirect="/Error500.html" />
</customErrors>
</system.web>
<system.webServer>
<httpErrors errorMode="DetailedLocalOnly" existingResponse="Auto">
<remove statusCode="403" />
<remove statusCode="404" />
<remove statusCode="500" />
<error statusCode="403" responseMode="File" path="Error403.html" />
<error statusCode="404" responseMode="File" path="Error404.html" />
<error statusCode="500" responseMode="File" path="Error500.html" />
</httpErrors>
</system.webServer>
Example 2: using aspx pages
<system.web>
<customErrors mode="RemoteOnly" defaultRedirect="/Error500.html" redirectMode="ResponseRewrite">
<error statusCode="403" redirect="/Error403.aspx" />
<error statusCode="404" redirect="/Error404.aspx" />
<error statusCode="500" redirect="/Error500.aspx" />
</customErrors>
</system.web>
<system.webServer>
<httpErrors errorMode="DetailedLocalOnly" existingResponse="Auto">
<remove statusCode="403" />
<remove statusCode="404" />
<remove statusCode="500" />
<error statusCode="403" responseMode="ExecuteURL" path="Error403.aspx" />
<error statusCode="404" responseMode="ExecuteURL" path="Error404.aspx" />
<error statusCode="500" responseMode="ExecuteURL" path="Error500.aspx" />
</httpErrors>
</system.webServer>
And in the aspx error pages you need to do something like this (example 404 page):
<%
Response.StatusCode = 404;
Response.TrySkipIisCustomErrors = true;
%>
Note: Using extension less urls in the customErrors section is not possible!. (without hacks)
One work around is to disable custom errors and let http errors handle the custom page. A friend has created such setup, when I find some time, I will share the code.
Background
A good custom error page will:
Show the real exception when you visit the problem page locally
Show a custom page when you visit the problem page remotely
Will not redirect, but simply show the error page content (because of seo reasons)
Will show the correct status code
So to clarify some options in our config:
<customErrors mode="RemoteOnly". You can specify here: On, Off, RemoteOnly.
On = Always show custom error pages
Off = Always show the real error
RemoteOnly = Show the error locally, but show the custom error page remotely.
So we want RemoteOnly for statement 1
<customErrors redirectMode="ResponseRewrite". You can specify here: ResponseRedirect or ResponseRewrite. The ResponseRedirect mode will redirect the error page to the custom error page. For a link crawler (SEO), this will result in 302 -> 500, but you want the link crawler to get a 500 error.
<httpErrors errorMode="DetailedLocalOnly". This the equivalent of the customErrors mode. Options that you have: Custom, Detailed, DetailedLocalOnly.
A good blog post which helped me a lot is: http://benfoster.io/blog/aspnet-mvc-custom-error-pages
Disclaimer: This is from my experience and not proven fact.
Both are used to define error handling for a website, but different software refers to different config elements.
customErrors are a legacy (backwards compatable) element, used by Visual Studio Development Server (aka. VSDS or Cassini).
httpErrors are the new element which is only used by IIS7.
This highlights the possible problem when developing ASP.NET websites while using VSDS instead of the local IIS.
Also, refer to this post by myself about how to handle error messages with IIS7, if you wish to have full control of the error output.
Summary:
Developing in VSDS - use customErrors
Publishing the site to IIS6 - use customErrors
Publishing the site to IIS7 - use httpErrors.
and if you develop with VSDS but publish to IIS7, then i guess u'll need both.
<customErrors> versus <httpErrors>
<customErrors>
still available in IIS7+
specify custom error pages for requests handled by ASP.NET
only handles requests within the ASP.NET application
static files such as HTML files or directory (“friendly”) URLs are not handled
<httpErrors>
introduced in IIS7
specify custom error pages for requests handled by IIS
handles requests within the ASP.NET application AND/OR handles requests outside the - ASP.NET application *
all files and URLs are handled *
Note: it is no longer necessary to use customErrors
Quoted source: Custom 404 and error pages in ASP.NET (excellent article)
ExecuteURL serves dynamic content such as an .aspx page (the path value has to be a server relative URL):
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Auto" defaultResponseMode="ExecuteURL" >
<remove statusCode="404"/>
<error statusCode="404" responseMode="ExecuteURL" path="/error.aspx" />
</httpErrors>
</system.webServer>
File serves a custom error file, such as a .html page:
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Auto" defaultResponseMode="File" >
<remove statusCode="404"/>
<error statusCode="404" path="404.html" />
</httpErrors>
</system.webServer>
Reference: HTTP Errors (www.iis.net)
for more details, read the www.iis.net link above
Errors section in web config is for providing custom http error handling approach there are two section, one customErrors inside the section system.web and another httpErrors inside the section system.webServer (as given below)
customErrors :
This section was in use before IIS 7 introduced, IIS 6 5 and before fully use this section for handling custom http errors according to http status code.
httpErrors :
IIS 7 and later use this section as well as customErrors section to handle custom http errors based on their file extensions if requested page extension register with ISAPI dll (.aspx, ashx, .asmx, .svc etc) like index.aspx then IIS pick up setting from customeErrors section else it pick up setting from httpErrors (IIS 7 hosted mode must be set as integrated mood not classic)
below are the examples that is for 404 error handling check link :
httperrors vs customerrors in webconfig , iis, asp.net