Related
We have an issue whereby Outlook is misbehaving because it is attempting to read an autodiscover.xml on our domain, specifically https://example.com/autodiscover/autodiscover.xml.
The email host says that we should configure the websitefirewall to return a timeout error. However, the site is hosted on Azure, and I don't see any option to do that.
Therefore, I was wondering if this could be done in MVC? I tried the following:
public class AutoDiscoverController : Controller
{
[Route("autodiscover/autodiscover.xml")]
public ActionResult Index()
{
return new HttpStatusCodeResult(HttpStatusCode.RequestTimeout);
}
}
...but it doesn't work; I see a 404 page instead. A breakpoint on the method also never gets hit.
Is it possible to create a route that mimics a non-existent file to return the timeout error?
Duplicate question update
There is a similar question at Dots in URL causes 404 with ASP.NET mvc and IIS. However, this question differs in that:
The answer doesn't work in MVC5
I cannot create a rule to recognise a trailing slash in the URL, because Outlook is generating the URL and I have no control over that
What else I've tried...
In RouteConfig, I defined a custom route. It doesn't work; the route never gets hit.
routes.MapRoute(
name: "AutoDiscover",
url: "autodiscover/autodiscover.xml",
defaults: new { controller = "AutoDiscover", action = "Index" });
As above, but using url: "autodiscover/*"
routes.IgnoreRoute("autodiscover.xml");
Defined a Route attribute on the controller itself, then enable routes.MapMvcAttributeRoutes();
I found an answer, thanks to Rick Strahl's answer here, and related blog post.
For some reason, defining a route in the RouteConfig never hits, but doing it at controller level does work. However, an additional step is needed, as pointed out by Nkosi to get it to work.
1. Enable MVC Attribute Routing
This wires up the routing attributes at controller-level (done in the next step)
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes(); // <-- Added this
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
2. Add the Route as an attribute
public class AutoDiscoverController : Controller
{
[Route("autodiscover/autodiscover.xml")]
public ActionResult Index()
{
return new HttpStatusCodeResult(HttpStatusCode.RequestTimeout);
}
}
3. Configure a route based on specific files in web.config
I believe this forces MVC to take over what IIS would usually handle (as XML is considered a "static" file).
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="dotless" path="*.less" verb="GET" type="dotless.Core.LessCssHttpHandler,dotless.Core" resourceType="File" preCondition="" />
<!-- Added this line -->
<add name="AutoDiscoverXmlFileHandler" path="autodiscover.xml" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" responseBufferLimit="0" />
</handlers>
</system.webServer>
Result
I am making a CORS POST request and setting the Content-Type header to json. This triggers a Preflight OPTIONS request to fire (this is good and expected)
This OPTIONS request is responded to with a 200 OK but this isn't coming from my WebAPI application.
I have a custom Message Handler in place and it never get's hit so the request is getting responded to by IIS prior to hitting ASP.NET it seems.
I have found several posts on the subject and they say the following
Make sure WebDav is uninstalled / removed / disabled - DONE
Make sure the OPTIONSVerbHandler is removed / changed to use aspnet_isapi.dll - TRIED BOTH
Make sure the extensionlessURLHandler includes the OPTIONS verb - DONE
However, my options request is still getting hijacked. By that I mean, IIS responds with at 200 OK but isn't including an Access-Control-Allow-Origin header in the response. It isn't including this header because it is never getting to my WebAPI CORS code that would set this header.
The two best posts I could find that sound like my issue are
here: JQuery stuck at CORS preflight and IIS ghost response
and here: http://brockallen.com/2012/10/18/cors-iis-and-webdav/
I have tried turning on Failed Request tracing (FERB) in IIS and set it to trace all 200 status codes. I don't ever see the options request being logged... Not sure if this means FERB doesn't track OPTIONS requests or if I need to change something in the FERB settings to make it track OPTIONS requests, Or if this is a clue to what my problem is?
This is ASP.NET WebAPI 2.0 running on IIS 7.5 (Also tested on IIS 8 and IISExpress with same results)
Doesn't matter what browser (Chrome, FF, and IE all fail the same way)
I have tried everything I can find on the subject and still can't fix my problem.
Help me StackOverflow, you're my only hope.
A couple of things you can try here, all web.config related, firstly modify your modules element to include the attribute runAllManagedModulesForAllRequests="true", as below:
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDavModule" />
</modules>
Then set your handlers to the below:
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="WebDav" />
<remove name="OPTIONSVerbHandler" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
This should do the trick, but if it doesn't, as a last resort you can force IIS to output the correct headers with the below:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
</customHeaders>
</httpProtocol>
</system.webServer>
Be wary of the wildcard value, you should really set this to the domain name that your site will be hosted on.
that's what worked for me after 4 hours of searching/experimenting:
<handlers>
<remove name="OPTIONSVerbHandler" />
<add name="OPTIONSVerbHandler" path="*" verb="OPTIONS" modules="IsapiModule" scriptProcessor="C:\Windows\System32\inetsrv\asp.dll" resourceType="Unspecified" requireAccess="None" />
</handlers>
I tried all of the above suggestions as well as others I found on SO and what mattered in my situation was we had Request Filtering enabled on IIS and the OPTIONS HTTP Verb was not in the list of allowed verbs. Once I added it I was able to sort out the rest of it.
I had the same issue and the following web.config settings fixed it for me.
<modules runAllManagedModulesForAllRequests="false">
<remove name="FormsAuthenticationModule" />
</modules>
<handlers>
<remove name="OPTIONSVerbHandler" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
I was then able to handle CORS OPTIONS requests manually in Application_BeginRequest.
I was originally using the library detailed in this blog post for handling CORS requests. The product I'm working on requires that runAllManagedModulesForAllRequests be set to false, though. This is why I had to set up a custom implementation, but if you don't have that requirement you should give that library a try. It worked great when I was able to have runAllManagedModulesForAllRequests set to true.
In our case it was request filtering in IIS disabling OPTIONS verb at the root web application level. Open up IIS Manager, click on root application, click on Request Filtering, if OPTIONS appears in list either remove or Allow Verb. Wish I had checked this first as lots of wasted time.
In my case, I missed the Microsoft.WebApi.Cors package.
Installed this package and configured it like so in the WebApiConfig class:
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.EnableCors(new EnableCorsAttribute("*","*","*"));
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
Please fine-tune this before using in production because you probably don't want to have wild-cards for everything
This is what worked for me:
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
Check if URLScan tool is installed on IIS.
When so check following section:
;
; The verbs (aka HTTP methods) listed here are those commonly
; processed by a typical IIS server.
;
; Note that these entries are effective if "UseAllowVerbs=1"
; is set in the [Options] section above.
;
GET
HEAD
POST
OPTIONS
I know this is an old post, but I just went through the exact same problem.
In my situation, I have CORS installed for both OWIN and WebAPI. The OWIN CORS middleware was intercepting the OPTIONS call long before it ever made it to the WebAPI stuff. Maybe this well help someone else in the future.
I have installed Microsoft.AspNet.WebApi.Cors & Microsoft.Owin.Cors for my oWin based WebAPI and added app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); at config like below:
public class Startup : IStartup, IAppStartup
{
public void Configuration(IAppBuilder app)
{
var config = this.GetInjectionConfiguration();
BootstrapperWebApi bootstrapperWebApi = (BootstrapperWebApi)this.GetBootstrapperWebApi(config);
bootstrapperWebApi.Initialize(true)
.EnableLogging()
.DisableWebApiDefaultExceptionHandler();
WebApiConfig.Register(config);
app.UseOwinExceptionHandler();
app.Use<LoggerMiddleware>();
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
//others stuff
}
I tried all the mentioned posts but nothing worked for me, then i shifted my ASP.Net Web API 2 service to windows server 2012 (IIS 8.5) and same service worked without any changes. So issue was specific to IIS 7.5 on windows 7 machine.
In my case I did this:
<verbs allowUnlisted="true" applyToWebDAV="true">
<remove verb="OPTIONS"/>
<add verb="OPTIONS" allowed="true"/>
</verbs>
</requestFiltering>
</security>
When I added <add verb="OPTIONS" allowed="true"/> to the web.config, the application failed to start with this error
HTTP Error 500.19 - Internal Server Error
The requested page cannot be accessed because the related configuration data for the page is invalid.
Cannot add duplicate collection entry of type 'add' with unique key attribute 'verb' set to 'OPTIONS'
So I had to remove it first.
I have the same issue. The OPTIONS request return 200 OK status but it does not contain Access-Control-Allow-Origin header. The problem was our customer network policy blocking the OPTIONS verb request and response the warning message with 200 OK status. I know this is the old post but I want to share my case for anyone needed.
One more case, maybe it will save time for somebody. When I used config with HttpConfiguration.EnableCors all was working fine but when I used web.config file it was failing with CORS errors. It started work after I removed the .vs folder.
<figure>
<img src="https://i.stack.imgur.com/CbRyM.png" alt="">
<figcaption> change the OptionsVerbHangle</figcaption>
</figure>
<figure>
<img src="https://i.stack.imgur.com/wjcMV.png" alt="Minha Figura">
<figcaption>Adicione * and in the case of php use fastcgimodule</figcaption>
</figure>
<figure>
<img src="https://i.stack.imgur.com/wRwpi.png" alt="Minha Figura">
<figcaption>Mapping to folder
</figcaption>
</figure>
<figure>
<img src="https://i.stack.imgur.com/hhqJi.png" alt="Minha Figura">
<figcaption>all verbs
</figcaption>
</figure>
<figure>
<img src="https://i.stack.imgur.com/86kKX.png" alt="Minha Figura">
<figcaption>Select script
</figcaption>
</figure>
Just follow the images below to unlock the colors in IIS
enter image description here
enter image description here
enter image description here
enter image description here
enter image description here
enter image description here
I rewrote my website from pure html file paths to MVC 4 extensionless urls.
Now I want to implement rule to redirect all requests to the old .html files to my home page.
In routeConfig.cs I tried this:
routes.MapRoute(
name: "Redirects",
url: "posts/{page}.html",
defaults: new { controller = "Home", action = "Index" }
);
But, no matter what I try, I get a 404. I looks like MVC is processing .html files and ignoring my Route entry.
I also tried:
routes.IgnoreRoute("posts/{file}.html");
to tell MVC to not process .html files but still no luck.
Any ideas what I"m doing wrong?
Please make routes.RouteExistingFiles to true as per below code snippet.
routes.RouteExistingFiles = true;
routes.MapRoute(name: "Redirects",
url: "HtmlPage.html",
defaults: new { controller = "Home", action = "Html", page = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Also edit your web.config and add PageHandlerFactory-Integrated-HTML handlers to the list of handlers as per below code snippet.
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="PageHandlerFactory-Integrated-HTML" path="*.html"
verb="GET,HEAD,POST,DEBUG" type="System.Web.UI.PageHandlerFactory"
resourceType="Unspecified" preCondition="integratedMode" />
</handlers>
Since you're migrating from HTML to MVC, I think you shouldn't make the migration part of your application.
Rather, use URL Rewrite module (URL Rewrite) to redirect requests.
You can use the IIS Management Console to configure the redirection rules, or edit web.config directly.
Here's a sample of a rule in web.config that can be relevant to your case:
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Html to MVC" stopProcessing="true">
<match url=".*/(.*).html" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" />
</conditions>
<action type="Redirect" url="/Index/{R:1}" redirectType="Found" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
It might not be the perfect rule for what you need (do some testing and tweaking), but I believe it is the way to do what you need. This way you'll be able to eventually get rid of the HTML redirection at some point and it won't be a part of your application; which also means that you don't need to recompile your application to make changes.
I have looked in this site and seen some discussionsthe on error 404. But I can not find the same one as mine.
I have an application build with ASP.NET MVC 4. The url routing has not problem at all when I run in Visual Studio 2010. However when I published the application to Windows 2008 R2 Enterprise server named "MyCompany" under IIS7.5's Default Web Site as an application named "Test", the routing url misses the application name "Test". Thus causes the error 404.
The url is suppossed to be "http://MyCompany/Test/Home/Index?fileType=Fin". However it shows "http://MyCompany/Home/Index?fileType=Fin".
If I deploy the application to different port saying 8080, it works fine with "http://MyCompany:8080/Test/Home/Index?fileType=Fin".
Thanks in advance if anyone can help.
My route function is -
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
My WebServer configuration is -
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true" />
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="1048576000" />
</requestFiltering>
</security>
</system.webServer>
Update:
Robert reminded me of the Javascript potential problem. He is right. After reviewed my codes again, I found the location of the problem. This function -
function OnChange(dropdown) {
var myindex = dropdown.selectedIndex;
top.location.href = "Home/Index?fileType=" + dropdown.options[myindex].value;
return true;
}
should be -
function OnChange(dropdown) {
var myindex = dropdown.selectedIndex;
top.location.href = "#Url.Content("~/")" + "Home/Index?fileType=" + dropdown.options[myindex].value;
return true;
}
I'm going to go out on a limb, and say you've likely hard coded a URL in your javascript instead of using one of the URL building functions. There are a number of ways around that, but you need to verify that is the case first. We would need to see the Index view (or the offending javascript file) to see how you are building the URL to be able to determine what exactly is wrong.
I am having trouble with Crystal Reports when using charts and images which use CrystalImageHandler.aspx. The image cannot display and I suspect this is due to a problem with MVC routing.
The path image path is similar to this:
src="/CrystalImageHandler.aspx?dynamicimage=cr_tmp_image_a8301f51-26de-4869-be9f-c3c9ad9cc85e.png"
With the URL similar to this:
localhost:01234/ViewCrystalReports.aspx?id=50
The image cannot be found prumably because it's looking in a non-existant directory. How can I change the path CrystalImageHandler.aspx is located at? I think if I were to reference from the root the problem would be solved but anything I change in Web.Config fails to work.
I should mention this is on a conventional aspx page, not a view etc
I solve this problem editing Web.Config file
Insert the following line:
<system.web>
...
<httpHandlers>
<add path="CrystalImageHandler.aspx" verb="GET" type="CrystalDecisions.Web.CrystalImageHandler, CrystalDecisions.Web, Version=13.0.2000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304"></add>
</httpHandlers>
...
*take care with write your number version (Version=xx.x.xxxx.x)
Figured it out. The routing was interfering with the CrystalImageHandler.aspx link that was being generated. Global.aspx has the following line to tell the routing engine to ignore resource files:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
but this isn't a conventional resource file, it's an aspx file for some reason (anyone know why?)
adding this fixed it:
routes.IgnoreRoute("{resource}.aspx/{*pathInfo}");
public class CrystalImageHandlerController : Controller
{
//
// GET: /Reports/CrystalImageHandler.aspx
public ActionResult Index()
{
return Content("");
}
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
var handler = new CrystalDecisions.Web.CrystalImageHandler();
var app = (HttpApplication)filterContext.RequestContext.HttpContext.GetService(typeof(HttpApplication));
if (app == null) return;
handler.ProcessRequest(app.Context);
}
}
This controller will invoke the handler. Just add a route to this as CrystalImageHandler.aspx, it can also be used with any sub path you'd like (in this case /reports). Something I could NEVER get the handler to do via configuration.
To view in local machine,you will add the following code in web config
<httpHandlers>
<add verb="GET" path="CrystalImageHandler.aspx" type="CrystalDecisions.Web.CrystalImageHandler, CrystalDecisions.Web,Version=10.2.3600.0, Culture=neutral, PublicKeyToken=692fbea5521e1304" />
</httpHandlers>
...............................
<appSettings>
<add key="CrystalImageCleaner-AutoStart" value="true" />
<add key="CrystalImageCleaner-Sleep" value="60000" />
<add key="CrystalImageCleaner-Age" value="120000" />
</appSettings>
The following code is for displaying in server
<system.webServer>
<handlers>
<add name="CrystalImageHandler.aspx_GET" verb="GET" path="CrystalImageHandler.aspx" type="CrystalDecisions.Web.CrystalImageHandler, CrystalDecisions.Web, Version=10.2.3600.0, Culture=neutral, PublicKeyToken=692fbea5521e1304" preCondition="integratedMode"/>
</handlers>
</system.webServer>
:) I will solve that problem in adding in web config
It's because the routing was interfering with the CrystalImageHandler.aspx. So either in Global.asax or routeConfig file we can ignore route for .aspx extension files. You can ignore .aspx extension route by adding following line.
routes.IgnoreRoute("{allaspx}", new {allaspx=#"..aspx(/.*)?"});