11

I am attempting to implement an MVC custom base view page in order to "override" the User property type. This will make my CustomPrincipal type accessible in any view.

After searching the web, I found Phil Haack's instructions for implementing a custom base view page. I followed the instructions exactly as they are written, but I ran into an issue while accessing the properties in the view.

When I open a view, any previous Html helper actions are underlined with the blue, squiggly line. When I put my cursor over the @Html portion, it reveals the error:

"Html is ambiguous, imported from the namespaces or types 'System.Web.WebPages, System.Web.Mvc'."

Now, I understand why I am receiving the message, but I don't understand how to fix it. I don't know why this would matter, but the current application was created in Visual Basic. As a secondary test, I created another MVC application in C# and attempted to implement the custom base view page. In the C# application it worked just fine. I can access my custom property from within the views.

I have scoured the web looking for an answer to this issue, but so far have not found anything. Has anybody else run into a similar issue?

For reference, I included my custom base view page and ~/Views/web.config below:

BaseViewPage

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using CCInfoController;

namespace CCInfo.Web.Mvc
{
    public class BaseViewPage<TModel> : WebViewPage<TModel>
    {
        public new CustomPrincipal User
        {
            get
            {
                return base.User as CustomPrincipal;
            }
        }

        public override void Execute()
        {
        }
    }
}

~/Views/web.config

<configuration>
  <configSections>
    <sectionGroup name="system.web.webPages.razor"
      type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup,
      System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral,
      PublicKeyToken=31BF3856AD364E35">
    <section name="host" 
       type="System.Web.WebPages.Razor.Configuration.HostSection,
       System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral,
       PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
    <section name="pages"
       type="System.Web.WebPages.Razor.Configuration.RazorPagesSection,
       System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral,
       PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
    </sectionGroup>
  </configSections>

  <system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory,
       System.Web.Mvc, Version=3.0.0.0, Culture=neutral,
       PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="CCInfo.Web.Mvc.BaseViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
        <add namespace="System.Web.WebPages"/>
        <add namespace="CCInfoController" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>
  ...
</configuration>
tereško
  • 58,060
  • 25
  • 98
  • 150
Ryan V
  • 480
  • 3
  • 13
  • Cant uderstand what you trying to do. Why WebViewPage? Why not view? There is no WebViewPage in MVC or i am misss something.And User Principal usualy is a part of HttpContext. – maxs87 Jun 19 '13 at 15:55
  • 1
    Actually, `WebViewPage` is in fact [a part of the MVC framework](http://msdn.microsoft.com/en-us/library/gg402107%28v=vs.98%29.aspx). And yes, the 'User' property is part of the `HttpContext` and is accessible via the view. What I want to be able to do is access that `User` property, but use the base view page to change the type of that property to my `CustomPrincipal` rather than `IPrincipal`. Make sense? – Ryan V Jun 19 '13 at 16:12
  • 2
    Honestly, I feel that this is too much messing around simply to avoid casting the User yourself. If you use it frequently, I would just create an extension method for IPrinciple that casts it. Much less effort, and no need to do the extra code in every page. Remember, you also have to derive from Controller as well, and possibly ApiController, and several others. This is the epitome of the O in SOLID, which is the Open/Closed principle. Inheritence violates OCP. – Erik Funkenbusch Jun 19 '13 at 17:12
  • @Mystere Man Being rather new to MVC (both the framework and pattern), I simply assumed this was the intended way to access something like this. After all, MVC provides this extensibility out of the box. I suppose you have a point with this being too messy. I will definitely keep your suggestion in mind, but I am still curious as to why my setup works in C# MVC and not Visual Basic MVC. I was really just looking for a best practice for accessing user roles / permissions in an MVC view. – Ryan V Jun 19 '13 at 17:18
  • @hitopp - best practice is to just cast it where you need it. It's simple and easy to do. My suggestion has nothing to do with MVC, it's a C# and VB language feature (extension methods), working with IPrinciple which is a .NET feature (not specific to MVC). Inheritance is often misused for cases like this. Yes, you CAN do it, but it doesn't mean you SHOULD do it. – Erik Funkenbusch Jun 19 '13 at 17:25
  • I suggest you read http://en.wikipedia.org/wiki/Open/closed_principle and http://msdn.microsoft.com/en-us/magazine/cc546578.aspx – Erik Funkenbusch Jun 19 '13 at 17:31

1 Answers1

4

You need to provide 2 versions of the WebViewPage, a generic and non-generic.

public class BaseViewPage<TModel> : WebViewPage<TModel>
{
}


public class BaseViewPage : WebViewPage
{
}
shekky
  • 139
  • 10