3

I'm trying to use ASP.NET WebPages to make sense of an existing site which uses static .html files (about 500 of them). Unfortunately, my SEO person is requiring that the site maintains its existing directory / filenames, so I need to use .html.

After finding this example, I tried adding the extension in web.config under compilation/buildProviders/ as:

<add extension=".html" type="System.Web.WebPages.Razor.RazorBuildProvider"/>

And adding an Assembly as well:

<add assembly="System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />

This still doesn't render the page. It is simply output as source. I also created a Global.asax at the root of the project and added this under Application_Start():

System.Web.Razor.RazorCodeLanguage.Languages.Add(
    "html", new System.Web.Razor.CSharpRazorCodeLanguage());
System.Web.WebPages.WebPageHttpHandler.RegisterExtension("html");

Still had no effect. Unfortunately, I'm drawing a blank on Google.

Community
  • 1
  • 1
Jack M.
  • 30,350
  • 7
  • 55
  • 67
  • Are you saying that you want to map requests for *.html to .cshtml files, or are you attempting to add Razor code to existing .html files and want them processed by ASP.NET? – Mike Brind Sep 05 '13 at 07:28
  • I want to `.html` files to automagically be parsed by Razor. By default, this action is performed on .cshtml files. 90% of what I'm looking for is `@Layout` and `@RenderPage` (for including other pages). – Jack M. Sep 05 '13 at 15:12

2 Answers2

4

I happened upon this question while trying to solve the same problem - although in my case, for curiosity's sake.

Here's what you need in your web.config file:

<system.web>
   <compilation>
      <buildProviders>
         <add extension=".html"
              type="System.Web.WebPages.Razor.RazorBuildProvider, System.Web.WebPages.Razor"/>
      </buildProviders>
   </compilation>
</system.web>
<system.webServer>
   <handlers>
      <add name="Html" verb="*" path="*.html"
           type="System.Web.Webpages, WebPageHttpHandler"/>
   </handlers>
</system.webServer>

This isn't enough on its own, though! We need to register the extension with WebPageHttpHandler.
Normally, you'd be able to do stuff like this in the _AppStart file - unfortunately, when the application starts (i.e when _AppStart executes), it iterates over the items in the SupportedExtensions of WebPageHttpHandler, so we can't actually register the extension in AppStart.
What I did is I made a new .dll assembly with the PreApplicationStartMethod attribute, as seen here, but you can also do it inside the Global.asax file's Application_Start method.

Finally, we also need to add "html" as an extension to the RazorCodeLanguage.Languages dictionary, so that the Razor engine can figure out how to compile the template.

Example Global.asax file:

<%@ Application Language="C#" %>
<script runat="server">
   void Application_Start(object sender, EventArgs e) 
   {
      System.Web.WebPages.WebPageHttpHandler.RegisterExtension("html");
      var languages = System.Web.Razor.RazorCodeLanguage.Languages;
      languages.Add("html", languages["cshtml"]);
   }       
</script>
Santiclause
  • 870
  • 1
  • 7
  • 12
  • +1 This works like a charm :) Though I was able to register in `_AppStart.chtml` without issue. – EdSF Jun 29 '14 at 17:15
  • You really shouldn't be able to - the `ExecuteStartPage(HttpApplication)` method in `ApplicationStartPage.cs` ends up calling `ExecuteStartPageInternal` with `WebPageHttpHandler.GetRegisteredExtensions()` as an IEnumerable. `GetRegisteredExtensions` returns a read-only wrapper for the _supportedExtensions array, but modifying that array likewise modifies the wrapper. `ExecuteStartPageInternal` iterates over this read-only wrapper until it finds an _AppStart with an extension in that wrapper - but because it's iterating over the wrapper, we can't modify the underlying array inside _AppStart. – Santiclause Jun 29 '14 at 18:57
  • I tinkered with this on default scaffolding (VS2013) for `ASP.net Web Site Razor 3` (not application so there is no `global.asax` even) and AFAIK, that _is_ WebPages. More spooky stuff - didn't need the `handler` section, `buildProvider` was enough. Tinkered further and added more random things like ".edsf" and boom - razor code, extension-less, etc. etc (just no intellisense). I have no idea why I'd ever actually use it though, so chalk it up to tinkering :) – EdSF Jun 30 '14 at 00:04
0

You want to use routing. Are you using webforms or MVC? Global.asax is a good start. Add the complete code here:

namespace Name
{
    public class Global : System.Web.HttpApplication
    {

        protected void Application_Start(object sender, EventArgs e)
        {
            RegisterRoutes(RouteTable.Routes);
        }

        protected void Session_Start(object sender, EventArgs e)
        {

        }

        protected void Application_BeginRequest(object sender, EventArgs e)
        {

        }

        protected void Application_AuthenticateRequest(object sender, EventArgs e)
        {

        }

        protected void Application_Error(object sender, EventArgs e)
        {

        }

        protected void Session_End(object sender, EventArgs e)
        {

        }

        protected void RegisterRoutes(RouteCollection routes)
        {
            routes.MapPageRoute("Route1", "OldPage.html", "~/NewPage.aspx");

        }

        protected void Application_End(object sender, EventArgs e)
        {

        }
    }
}

Obviously you don't want to manually add 500 routes but you can add url filters.

See: http://msdn.microsoft.com/en-us/library/cc668201.ASPX

ASP.NET routing enables you to use URLs that do not have to map to specific files in a Web site.

Zerkey
  • 795
  • 1
  • 6
  • 16
  • I'm actually using ASP.NET WebPages so that I can just make files in the package and upload to Azure. I'd rather not involve MVC or WebForms. But I'd like to be able to re-use the templates and content later if the project evolves. – Jack M. Sep 05 '13 at 03:44
  • My apologies, maybe there is a simpler way to do it within WebPages. The only easy solution I know of is to use MVC... define {resource}.html in your routing table and specify a Controller, and then have the controller pick up a View based on the {resource} specified. I fear for your sanity if you have to manually reroute 500 urls. PS. MVC uses Razor too. – Zerkey Sep 05 '13 at 03:52
  • I have done some in MVC and that's where I learned of Razor. As for the routes, that's why I'm shooting for this plan: I can automate creating the files on the filesystem, just need to use .html in ALL the URLs instead of .cshtml. – Jack M. Sep 05 '13 at 03:58