Question

So, I personally think this is sort of whack.

I put a .aspx template in a nonstandard location. In this example, it has a virtual path of ~/Content/Sites/magical/Index.aspx.

I then created my own view engine as a test, which extends WebFormsViewEngine:


public class MagicalWebFormsViewEngine : WebFormViewEngine
{
    public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
    {
        string viewTemplatePath = "~/Content/Sites/magical/" + viewName + ".aspx";
        string masterTemplatePath = string.Empty;
        return new ViewEngineResult(
            this.CreateView(controllerContext, viewTemplatePath, masterTemplatePath),
            this
        );
    }
}

The template looks like this:


<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Plain.Master" Inherits="System.Web.Mvc.ViewPage<MySoln.Client.Presentation.MyPresenter>" %>
...
<%: Model.SomePresenterSpecificMember %>

If I leave the strongly-typed declaration in the Inherits attribute of the Page declaration, I get the following exception:

Parser Error Message: Could not load type 'System.Web.Mvc.ViewPage<MySoln.Client.Presentation.MyPresenter>'.

However, if I change the template to use a weakly-typed page model, and instead use a cast on the Model member in the template itself, it works:


<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Plain.Master" Inherits="System.Web.Mvc.ViewPage" %>
...
<% var omg = (MySoln.Client.Presentation.MyPresenter) Model; %>
<%: omg.SomePresenterSpecificMember %>

So, my question is, why does the former barf and the latter work? I'd rather not cast Model to one of my presenter types in a tag at the top of every template.

Thanks!

Was it helpful?

Solution

Just make sure that you have the following web.config file at the root of your custom view engine path:

<?xml version="1.0"?>

<configuration>
  <system.web>
    <httpHandlers>
      <add path="*" verb="*" type="System.Web.HttpNotFoundHandler"/>
    </httpHandlers>

    <!--
        Enabling request validation in view pages would cause validation to occur
        after the input has already been processed by the controller. By default
        MVC performs request validation before a controller processes the input.
        To change this behavior apply the ValidateInputAttribute to a
        controller or action.
    -->
    <pages
        validateRequest="false"
        pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
        pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
        userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <controls>
        <add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />
      </controls>
    </pages>
  </system.web>

  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />

    <handlers>
      <remove name="BlockViewHandler"/>
      <add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
    </handlers>
  </system.webServer>
</configuration>

You could copy-paste the web.config file automatically generated by the default template and located in ~/views/web.config into ~/content/web.config.

Basically the important part is :

pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, ..."

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top