Invoke ASP.NET MVC Controller When Requesting .html file
Asked Answered
C

2

5

I need to add some new life to a legacy application :)

I'd like to call an MVC controller when a "static" HTML page is requested in order to add some markup to the page before returning it to the client.

I tried to follow the approach found in this thread: How to read web.config settings in .html page?

...but even though I have this route defined:

routes.MapRoute(
    name: "Topic", 
    url: "html/{fileName}.html", 
    defaults: new { controller = "Topic", action = "Index" });

the controller is not being called. I have my web.config defined with:

<remove name="WebServiceHandlerFactory-Integrated" />
<add name="HTML" path="*.html" verb="*" 
    type="System.Web.UI.PageHandlerFactory" 
    resourceType="File" preCondition="integratedMode" />

I suspect that I need to call something else besides the PageHandlerFactory or perhaps the issue is something entirely different.

UPDATE: My dev environment is working with integrated pipeline mode, but I need to check if my production environment will support it.

Caboodle answered 3/7, 2012 at 21:20 Comment(1)
Are you running in IIS7+ integrated pipeline mode?Sassan
R
6

If you do this:

routes.RouteExistingFiles = true;

You should find this works - even without the handler addition. In the controller you can load the HTML directly using the HostingEnvironment.VirtualPathProvider's GetFile method and do something with it - or better still just use a normal MVC view that renders the same content as the static file, just with your additions.

Although be aware that this means any files that are potentially caught by any routes will be pushed into the MVC pipeline. This isn't generally a concern, however, if decent separation of routes and physical paths is used.

Rankle answered 3/7, 2012 at 22:10 Comment(2)
The real answer to the question is to do both what Andras and Scott suggested. I tested both with and without the update to the routes (per Andras) and with and without the web.config settings (per Scott) and they are both required to make it work for what I am trying to do. Thanks, guys!Caboodle
I added some IgnoreRoutes rules to open the application up to other static content that doesn't require processing by the server.Caboodle
R
3

I setup the same situation as you and it worked well for me, so you have the key components in place. Some things to keep in mind for the testing and troubleshooting:

Your web.config does need the build provider for the html extension:

<system.web>
    <compilation>
      <buildProviders>
        <add extension=".html"
             type="System.Web.Compilation.PageBuildProvider" />
      </buildProviders>
    </compilation>
</system.web>

A copy and paste of your handlers works for me, so that looks good.

And a copy and paste of your MapRoute works for me too, although I used the default Home controller in a clean project. So as a double check just confirm that you have a controller called Topic with an ActionResult method called Index().

And make sure that your url is localhost.com:{port}/html/test.html with the /html/ in the path since your rule asks for that.

Another good test is to change your MapRoute to use aspx instead and test an aspx page and see if that works. That will confirm whether or not it's the IIS mappings or if it's the MVC rules. If it works with aspx then the issue is related to the handler, but if it fails with aspx too then it's something with MVC.

Also confirm that you're using IIS Express and not Cassini. Cassini will not handle that correctly, but IIS Express will. You can confirm by right-clicking on your project and you should see a menu option called "Use Visual Studio Development Studio...". That will only exist if you are currently using IIS Express.

Rheumatic answered 3/7, 2012 at 22:10 Comment(4)
I don't think this helps if you want the request to hit an MVC controller - the page will not be executed directly, as it is intended to be when the PageBuildProvider is used, but instead the request is to be passed to an MVC controller, which will then end up rendering a view (could be ASPX, could be Razor or whatever) on behalf of a URL with the .html extensionRankle
@Andras Zoltan, you're right, accounting for the existing file you need to add the routes.RouteExistingFiles = true from your answer.Rheumatic
As I stated above, the working fix for me was to integrate the response from both Scott and Andras. I had to pick one so I marked Andras' as the answer because he added the pointer to the route configuration which wasn't covered in this question or the one I originally linked to.Caboodle
I've +1d here to reflect your comment @CraigShoemakerRankle

© 2022 - 2024 — McMap. All rights reserved.