1

I am looking at the ASP.NET MVC4 application which is calling Server.TransferRequest("Error.cshtml") while executing one of the requests where Foo.cshtml is a view page residing in the root folder of the application. Everything is working fine on our old server, but once I deployed this app to our new 2012r2 server with IIS8 I am getting following error page:

Description: The type of page you have requested is not served because it has been explicitly forbidden. The extension '.cshtml' may be incorrect. Please review the URL below and make sure that it is spelled correctly.

Requested URL: /Error.cshtml

Why is that? How to make TransferRequest work? What setup to perform on new server? To reproduce you can quite simply create a new ASP.NET MVC5 project, add Error.cshtml razor page to its folder, then in the Index action of HomeController call HttpContext.Server.TransferRequest("Error.cshtml") and preview, you should get the same error as above.

Once I put a breakpoint in Application_Error method in Global.Asax.cs and preview the app, I get an exception:

Message: Path '/WebApplication1/Error.cshtml' is forbidden. at System.Web.HttpForbiddenHandler.ProcessRequest(HttpContext context) at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

Also, if I deploy mew ASP.NET MVC5 test app calling the TransferRequest to our old server (server 2008), it is still not working and throws an exception... So it seems like both old server and the original ASP.NET MVC4 app are somehow magically configured to make this thing work...

Michal Hosala
  • 5,570
  • 1
  • 22
  • 49
  • You'd typically not directly call a cshtml file like that. If there's no razor markup in it, you could just rename the file to .html instead and call to that. Otherwise, you'd need to make a controller for that Error.cshtml view and redirect to the controller action which will call the Error view. – KSib Jan 05 '18 at 16:46
  • @KSib I know this is not typical and I know how to work around this issue, but I have application which clearly is able to perform this action and execute the razor page, but I cannot replicate that behavior. – Michal Hosala Jan 05 '18 at 17:34
  • Have you checked the values for `webpages:enabled` in your root web.config file's app settings across all of your test apps? I believe you have to have this enabled (set to true) in order for .cshtml files to render without a controller. https://stackoverflow.com/questions/4886095/what-is-the-function-of-webpagesenabled-in-mvc-3-web-config – Tommy Jan 05 '18 at 18:23
  • See [How to simulate Server.Transfer in ASP.NET MVC?](https://stackoverflow.com/q/799511/181087). However, as [this answer](https://stackoverflow.com/a/799524/181087) correctly points out, `Server.TransferRequest` was only required in ASP.NET before there was any such thing as routing. Both of these approaches serve a resource (without a redirect, which does a round trip) depending on a condition. It would probably make more sense to find a way to handle your use case with routing than to waste time trying to work out how your old server is configured. – NightOwl888 Jan 05 '18 at 18:37
  • There apparently is another instance of that setting in the web.config inside the views folder as well. I am not sure if one overrides the other or not. – Tommy Jan 05 '18 at 18:40
  • @NightOwl888 unfortunately I don't own the code, I am only supposed to provide an infrastructure to run the app on. – Michal Hosala Jan 05 '18 at 18:50

3 Answers3

0

Pleas check if .cshtml is listed as a MIME type in your old server for the application's context. If this is the case, then you can (against recommendation) add .cshtml as a MIME type in the application's context. You could add a MIME type on a higher level, such as site or server and your application's context should inherit it but it is not recommended, unless you need to share the definition between multiple applications.

DISCLAIMER Giving users direct access to .cshtml is not considered best practice. If Error.cshtml is intended to be served as static content then you should rename it and rewrite it as HTML. If you set .cshtml as an allowed MIME type then you may be allowing users to inspect every .cshtml file in your web application. Alternatively you could write a controller to serve the content you need, for example:

public ActionResult CustomError()
{
   return View("Error");
} 
....   
HttpContext.Server.TransferRequest("CustomError")

Though I would recommend to use Exception Filters

Emilio Lucas Ceroleni
  • 1,559
  • 2
  • 9
  • 13
  • Thank you, but cshtml is not listed among MIME types for my old application and the Error.cshtml in question cannot be accessed directly via browser as well. But surprisingly can be transfered to, executed, and rendered back to end user. Address bar doesn't contain Error.cshtml of course as that is what TransferRequest does. – Michal Hosala Jan 05 '18 at 18:12
0

By default, a new MVC 5 application generates a web.config file with the following lines:

Root web.config file

<configuration>
  <appSettings>
    <add key="webpages:Version" value="3.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
  </appSettings>

Views folder web.config

  <appSettings>
    <add key="webpages:Enabled" value="false" />
  </appSettings>

When the webpages:Enabled is set to false, rendering of .cshtml and .vbhtml files directly are prevented by the application. Change this value to true, save and recompile. Your application should now render these files.

Tommy
  • 39,592
  • 10
  • 90
  • 121
0

In the end the root cause of the problem is rather silly.. Yes, you have to have webpages:Enabled set to true in web.config, but that is the default value in MVC4 anyway. However, the difference lies in the url:

  • localhost/WebApp results into error about cshtml pages being forbidden
  • localhost/WebApp/ renders just fine

So the difference has to be somewhere in routing, which I am not going to investigate further as it is buried in HttpServerUtility.TransferRequest. Both of the requests hit the HttpContext.Server.TransferRequest("Error.cshtml") breakpoint, but result is different.

Michal Hosala
  • 5,570
  • 1
  • 22
  • 49