一般遗传 ViewPage<> 和一个新的财产

安装:

CustomViewEngine

CustomController 根据

CustomViewPage Base /此数据库添加了新属性。 "MyCustomProperty"/

问题:

什么时候 view 例如,严格输入:
<@ Page Inherits="CustomViewPage<mycustomobject" mycustomproperty="Hello">

, 我得到一个编译错误 "Parser", 批准 MyCustomProperty 不是公共财产 System.Web.Mvc.ViewPage

我做了很多样品和错误 /见下文/, 要查看导致此错误的原因,并提出以下结论:

仅在我声明时发生错误 "MyCustomProperty" 或指令中的任何其他财产 @Page view.

错误将始终显示 "System.Web.Mvc.ViewPage", 而不是宣布的课程 inherits="..".
</mycustomobject">
已邀请:

石油百科

赞同来自:

更新:看起来像

找到了另一种方法来做到这一点,至少在较新的版本中看起来更容易 ASP.NET MVC. /在下面复制他的评论

/

我不确定这是新的 ASP.NET MVC 3, 但是当我更改了属性时
Inherits 参考文献 generic 在语法中 C# 在
句法 CLR, 标准
ViewPageParserFilter

正确分析了通用 --
不需要
CustomViewTypeParserFilter

. 使用justin的例子,这
意味着交换


<%@ Page Language="C#" MyNewProperty="From @Page directive!"
Inherits="JG.ParserFilter.CustomViewPage<mvcapplication1.models.foomodel>





&lt;%@ Page Language="C#" MyNewProperty="From @Page directive!"` 
Inherits="JG.ParserFilter.CustomViewPage`1[MvcApplication1.Models.FooModel]&gt;


原始答案较低

:

OK, 我解决了这个问题。 这是一个令人迷人的运动,解决方案是非激动的,但一旦你第一次制作工作,就不会太困难。

这是主要问题:解析器 ASP.NET 页面不支持泛型作为页面类型。

方法 ASP.NET MVC 它是为了解决这个问题是欺骗基本页面分析仪,强迫他认为页面并不普遍。 他们通过建设来做到这一点 custom
http://msdn.microsoft.com/en-u ... .aspx
和 custom
http://msdn.microsoft.com/en-u ... .aspx
. 解析器过滤器正在寻找通用类型,如果他发现它,则不会使其更改为Universal类型 ViewPage, 解析器。 ASP.NET 没有选择。 然后,在汇编页面的生命周期之后,他们的用户类 Page builder 一般类型再次变为变化。

它是因为类型 generic ViewPage 源自类型 non-generic ViewPage, 以及指令中指定的所有有趣属性 @Page, 存在于基本课程中 /non-generic/. 因此,实际上,当在指令中指定属性时 @Page, 检查这些属性是否符合非标准基类。 ViewPage.

在任何情况下,它在大多数情况下都能很好,但不是在你的情况下,因为他们很难编码 ViewPage 与其实现页面过滤器的通用基本类型一样,不提供更改它的简单方法。 这就是你继续看到的原因 ViewPage 在他的错误消息中,由于何时发生错误 ASP.NET 更改占聚合 ViewPage, 当他改变普通的地方 ViewPage 在汇编之前。

纠正是为了创建以下内容的自己版本:

Pareraser过滤页面 - 这几乎是一个精确的副本 ViewTypeParserFilter.cs 在源头 MVC, 唯一的区别,他指的是您的自定义类型 ViewPage 和 Page builder 反而 MVC

Page 建设者是相同的 ViewPageControlBuilder.cs 在源头 MVC, 但他把课程放在自己的命名空间中,而不是在他们身上。

制作您的用户类 viewpage 直接从 System.Web.Mvc.ViewPage /没有通用版本/. 将任何用户属性附加到此新的非通用类。

输出普遍等级 #3,, 从实现中复制代码 ViewPage 来源 ASP.NET MVC.

重复 #2, #3, 和 #4 对于用户控件 /@Control/, 如果还需要指令控制指令的自定义属性。

然后你需要改变 web.config 在表示目录中 /但不是 web.config 基本应用程序/, 使用这些新类型 MVC 默认。

我附上了一些代码的例子,说明它是如何工作的。 非常感谢Fila Haak,谁帮助我了解它,虽然我也必须在源代码中挖很多 MVC 和 ASP.NET, 真正了解它。

首先,我会开始 web.config 所需的更改 web.config:


<pages pagebasetype="JG.ParserFilter.CustomViewPage" pageparserfiltertype="JG.ParserFilter.CustomViewTypeParserFilter" usercontrolbasetype="JG.ParserFilter.CustomViewUserControl" validaterequest="false">


现在这里是Pages解析器过滤器 /#1 更高/:


namespace JG.ParserFilter {
using System;
using System.Collections;
using System.Web.UI;
using System.Web.Mvc;

internal class CustomViewTypeParserFilter : PageParserFilter
{

private string _viewBaseType;
private DirectiveType _directiveType = DirectiveType.Unknown;
private bool _viewTypeControlAdded;

public override void PreprocessDirective/string directiveName, IDictionary attributes/ {
base.PreprocessDirective/directiveName, attributes/;

string defaultBaseType = null;

// If we recognize the directive, keep track of what it was. If we don't recognize
// the directive then just stop.
switch /directiveName/ {
case "page":
_directiveType = DirectiveType.Page;
defaultBaseType = typeof/JG.ParserFilter.CustomViewPage/.FullName; // JG: inject custom types here
break;
case "control":
_directiveType = DirectiveType.UserControl;
defaultBaseType = typeof/JG.ParserFilter.CustomViewUserControl/.FullName; // JG: inject custom types here
break;
case "master":
_directiveType = DirectiveType.Master;
defaultBaseType = typeof/System.Web.Mvc.ViewMasterPage/.FullName;
break;
}

if /_directiveType == DirectiveType.Unknown/ {
// If we're processing an unknown directive /e.g. a register directive/, stop processing
return;
}


// Look for an inherit attribute
string inherits = /string/attributes["inherits"];
if /!String.IsNullOrEmpty/inherits// {
// If it doesn't look like a generic type, don't do anything special,
// and let the parser do its normal processing
if /IsGenericTypeString/inherits// {
// Remove the inherits attribute so the parser doesn't blow up
attributes["inherits"] = defaultBaseType;

// Remember the full type string so we can later give it to the ControlBuilder
_viewBaseType = inherits;
}
}
}

private static bool IsGenericTypeString/string typeName/ {
// Detect C# and VB generic syntax
// REVIEW: what about other languages?
return typeName.IndexOfAny/new char[] { '&lt;', '/' }/ &gt;= 0;
}

public override void ParseComplete/ControlBuilder rootBuilder/ {
base.ParseComplete/rootBuilder/;

// If it's our page ControlBuilder, give it the base type string
CustomViewPageControlBuilder pageBuilder = rootBuilder as JG.ParserFilter.CustomViewPageControlBuilder; // JG: inject custom types here
if /pageBuilder != null/ {
pageBuilder.PageBaseType = _viewBaseType;
}
CustomViewUserControlControlBuilder userControlBuilder = rootBuilder as JG.ParserFilter.CustomViewUserControlControlBuilder; // JG: inject custom types here
if /userControlBuilder != null/ {
userControlBuilder.UserControlBaseType = _viewBaseType;
}
}

public override bool ProcessCodeConstruct/CodeConstructType codeType, string code/ {
if /codeType == CodeConstructType.ExpressionSnippet &amp;&amp;
!_viewTypeControlAdded &amp;&amp;
_viewBaseType != null &amp;&amp;
_directiveType == DirectiveType.Master/ {

// If we're dealing with a master page that needs to have its base type set, do it here.
// It's done by adding the ViewType control, which has a builder that sets the base type.

// The code currently assumes that the file in question contains a code snippet, since
// that's the item we key off of in order to know when to add the ViewType control.

Hashtable attribs = new Hashtable//;
attribs["typename"] = _viewBaseType;
AddControl/typeof/System.Web.Mvc.ViewType/, attribs/;
_viewTypeControlAdded = true;
}

return base.ProcessCodeConstruct/codeType, code/;
}

// Everything else in this class is unrelated to our 'inherits' handling.
// Since PageParserFilter blocks everything by default, we need to unblock it

public override bool AllowCode {
get {
return true;
}
}

public override bool AllowBaseType/Type baseType/ {
return true;
}

public override bool AllowControl/Type controlType, ControlBuilder builder/ {
return true;
}

public override bool AllowVirtualReference/string referenceVirtualPath, VirtualReferenceType referenceType/ {
return true;
}

public override bool AllowServerSideInclude/string includeVirtualPath/ {
return true;
}

public override int NumberOfControlsAllowed {
get {
return -1;
}
}

public override int NumberOfDirectDependenciesAllowed {
get {
return -1;
}
}

public override int TotalNumberOfDependenciesAllowed {
get {
return -1;
}
}

private enum DirectiveType {
Unknown,
Page,
UserControl,
Master,
}
}
}


这是一个班级 Page builder /#2 更高/:


namespace JG.ParserFilter {
using System.CodeDom;
using System.Web.UI;

internal sealed class CustomViewPageControlBuilder : FileLevelPageControlBuilder {
public string PageBaseType {
get;
set;
}

public override void ProcessGeneratedCode/
CodeCompileUnit codeCompileUnit,
CodeTypeDeclaration baseType,
CodeTypeDeclaration derivedType,
CodeMemberMethod buildMethod,
CodeMemberMethod dataBindingMethod/ {

// If we find got a base class string, use it
if /PageBaseType != null/ {
derivedType.BaseTypes[0] = new CodeTypeReference/PageBaseType/;
}
}
}
}


但用户类的页面 view: 非门底座 /#3 更高/ 和一般衍生类 /#4 更高/:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Diagnostics.CodeAnalysis;
using System.Web.Mvc;

namespace JG.ParserFilter
{
[FileLevelControlBuilder/typeof/JG.ParserFilter.CustomViewPageControlBuilder//]
public class CustomViewPage : System.Web.Mvc.ViewPage //, IAttributeAccessor
{
public string MyNewProperty { get; set; }
}

[FileLevelControlBuilder/typeof/JG.ParserFilter.CustomViewPageControlBuilder//]
public class CustomViewPage<tmodel> : CustomViewPage
where TModel : class
{
// code copied from source of ViewPage<t>

private ViewDataDictionary<tmodel> _viewData;

public new AjaxHelper<tmodel> Ajax
{
get;
set;
}

public new HtmlHelper<tmodel> Html
{
get;
set;
}

public new TModel Model
{
get
{
return ViewData.Model;
}
}

[SuppressMessage/"Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly"/]
public new ViewDataDictionary<tmodel> ViewData
{
get
{
if /_viewData == null/
{
SetViewData/new ViewDataDictionary<tmodel>///;
}
return _viewData;
}
set
{
SetViewData/value/;
}
}

public override void InitHelpers//
{
base.InitHelpers//;

Ajax = new AjaxHelper<tmodel>/ViewContext, this/;
Html = new HtmlHelper<tmodel>/ViewContext, this/;
}

protected override void SetViewData/ViewDataDictionary viewData/
{
_viewData = new ViewDataDictionary<tmodel>/viewData/;

base.SetViewData/_viewData/;
}

}
}


但是用户控件的相应类 /#5 更高/ :


namespace JG.ParserFilter
{
using System.Diagnostics.CodeAnalysis;
using System.Web.Mvc;
using System.Web.UI;

[FileLevelControlBuilder/typeof/JG.ParserFilter.CustomViewUserControlControlBuilder//]
public class CustomViewUserControl : System.Web.Mvc.ViewUserControl
{
public string MyNewProperty { get; set; }
}

public class CustomViewUserControl<tmodel> : CustomViewUserControl where TModel : class
{
private AjaxHelper<tmodel> _ajaxHelper;
private HtmlHelper<tmodel> _htmlHelper;
private ViewDataDictionary<tmodel> _viewData;

public new AjaxHelper<tmodel> Ajax {
get {
if /_ajaxHelper == null/ {
_ajaxHelper = new AjaxHelper<tmodel>/ViewContext, this/;
}
return _ajaxHelper;
}
}

public new HtmlHelper<tmodel> Html {
get {
if /_htmlHelper == null/ {
_htmlHelper = new HtmlHelper<tmodel>/ViewContext, this/;
}
return _htmlHelper;
}
}

public new TModel Model {
get {
return ViewData.Model;
}
}

[SuppressMessage/"Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly"/]
public new ViewDataDictionary<tmodel> ViewData {
get {
EnsureViewData//;
return _viewData;
}
set {
SetViewData/value/;
}
}

protected override void SetViewData/ViewDataDictionary viewData/ {
_viewData = new ViewDataDictionary<tmodel>/viewData/;

base.SetViewData/_viewData/;
}
}
}

namespace JG.ParserFilter {
using System.CodeDom;
using System.Web.UI;

internal sealed class CustomViewUserControlControlBuilder : FileLevelUserControlBuilder {
internal string UserControlBaseType {
get;
set;
}

public override void ProcessGeneratedCode/
CodeCompileUnit codeCompileUnit,
CodeTypeDeclaration baseType,
CodeTypeDeclaration derivedType,
CodeMemberMethod buildMethod,
CodeMemberMethod dataBindingMethod/ {

// If we find got a base class string, use it
if /UserControlBaseType != null/ {
derivedType.BaseTypes[0] = new CodeTypeReference/UserControlBaseType/;
}
}
}
}


最后,这是一个例子 View, 这在行动中显示:


&lt;%@ Page Language="C#" MyNewProperty="From @Page directive!" Inherits="JG.ParserFilter.CustomViewPage<mvcapplication1.models.foomodel>" %&gt;
&lt;%=Model.SomeString %&gt;
<br/><br/>this.MyNewPrroperty = &lt;%=MyNewProperty%&gt;


</mvcapplication1.models.foomodel></tmodel></tmodel></tmodel></tmodel></tmodel></tmodel></tmodel></tmodel></tmodel></tmodel></tmodel></tmodel></tmodel></tmodel></tmodel></tmodel></tmodel></tmodel></t></tmodel></pages></mvcapplication1.models.foomodel>

要回复问题请先登录注册