【问题标题】:Public variables in MVC 3 Razor _ViewStartMVC 3 Razor _ViewStart 中的公共变量
【发布时间】:2010-11-27 11:24:08
【问题描述】:

我正在 MVC 3 附带的新 Razor 引擎上构建一个站点(并且喜欢新语法!)。但是,我对使用公共属性/常量感到茫然。我知道使用 WebForms 我们可以在后面的代码中添加一个公共属性:

public string ImageFolder { get; set; }

我想在我的视图可以访问的一个全局位置定义重要变量,从 CSS 文件和图像的路径开始:

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
    var ContentFolder = "~/Content";
    var CssFolder = ContentFolder + "/Stylesheets";
    var ImageFolder = ContentFolder + "/Images";
}

我尝试将上述代码块放入_Layout 以及_ViewStart 中。但是,从子视图访问它们会惨遭失败。我想在上面的代码块中定义一个公共属性,但它没有编译。

解决方案?

  • 据我所知,没有人在 Razor 中使用代码隐藏。
  • 我想我应该能够从默认视图继承并在那里定义我的属性(如described on Stack)。

但我强烈希望应该有一种更简单的方法来完成如此简单的事情?

【问题讨论】:

  • “我强烈希望应该有一种更简单的方法”为您的视图定义一个基类并不难,并且可以为您提供很好的灵活性。

标签: global-variables asp.net-mvc-3 razor


【解决方案1】:

我决定采用另一条路径,并扩展 UrlHelper 以提供我认为可能需要的所有三个文件夹的路径:

public static class ExtensionMethods
{
    private const string ImagesFolder = "~/Images";
    private const string StylesheetsFolder = "~/Stylesheets";
    private const string ScriptsFolder = "~/Scripts";

    public static string Images(this UrlHelper url)
    {
        return url.Content(ImagesFolder);
    }

    public static string Stylesheets(this UrlHelper url)
    {
        return url.Content(StylesheetsFolder);
    }

    public static string Scripts(this UrlHelper url)
    {
        return url.Content(ScriptsFolder);
    }
}

一切顺利...几乎:-) 我现在想知道是否有一个地方可以定义using MyNamespace.Helper 语句,以便这些扩展方法在应用程序范围内可用。在过去,我们会在 web.config 中添加一个条目:

<system.web>
    <pages>
        <namespaces>
            <add namespace="MyNamespace.Helper"/>
        </namespaces>
    </pages>
</system.web>

这似乎不适用于 Razor :-( 我尝试在 _ViewStart.cshtml 中添加 using 语句,但也没有运气 - 我的扩展方法可见的唯一方法是在特定页面上添加 using 语句,这又不理想。

有什么建议吗?大家有没有看过 Razor 的页面解析和传递顺序的解释?

【讨论】:

  • 检查我更新的答案,它应该澄清一些事情,让我知道你的想法。
【解决方案2】:

您可以创建一个文件夹“App_Code”并创建一个文件“GlobalVal.cshtml”。 下面是文件中的示例代码:

@functions{
    public static readonly string __siteHome = "http://www.example.com";
    public static readonly string __siteResource = "http://resource.example.com";
}

下面是一个使用它的示例:

<a href="@GlobalVal.__siteHome/home/index">@GlobalVal.__siteHome</a>

【讨论】:

  • 这几乎是我们最终在另一个项目中所做的,辅助方法是在 Razor 中使用的一种享受。
【解决方案3】:

使用PageData 属性:

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
    PageData.Add("ContentFolder", "~/Content");
}

_Layout.cshtml:内部

<%=PageData["ContentFolder"]%>

【讨论】:

    【解决方案4】:

    在_layout视图中

    @{
    App.AnyName = "abc";
    }
    

    在继承视图中

    @{
    
        var anyVariable = App.AnyName;
    
    }
    

    【讨论】:

    • 看起来不错,以后遇到这个问题一定要试试!
    【解决方案5】:

    只需将常量放在 app_code 文件夹内的公共模块中,或者如果您不想这样做,只需在 app_code 中创建一个类并使用 using (imports) 关键字在每个中导入命名空间(类名)查看,您可以这样使用它。

    或者,如果这样做有意义,只需将它们添加到您的视图模型中 - 请记住,将这些变量添加到您的模型中可能没有意义,但将它们添加到您的视图模型中是有意义的!这就是视图模型的用途,这个视图模型可以从公共模块或类中获取常量值,或者您甚至可以在您的实际视图模型本身中设置它,这样您将只在一个地方定义值并且您不需要在每个视图中使用任何命名空间导入 :)

    让我知道它是怎么回事,如果还有什么我可以做的来帮助你。

    在 vb.net 中,但与 csharp 相同,因为它是 vb,所以很容易理解。

    Public class YourModel
    
        // this is where you have the normal model you have... No big deal
    
    End Class
    
    ...
    
    // now you make the view model urself
    
    ...
    
    Public class MyViewModel
    
        Public MyNormalModel as YourModel
    
        //notice we r declaring ur normal model as a variable, u can use a property instead
    
        Public MyPathConstant1 as string = "abc"
    
        Public MyPathConstant2 as string = "abc"
    
        Public MyPathConstant3 as string = "abc"
    
    End Class
    

    现在,您必须将 MyNormalModel 的值设置为您当前的模型实例,尽管您可以在您的控制器中执行此操作,但最好在 MyViewModel 类中创建一个方法,该方法将您当前模型的副本作为参数并执行将 MyNormalModel 设置为我们刚刚传入参数的当前模型。

    您仍然可以在控制器中进行该调用,但另一方面,人们更喜欢做的是,与其将整个普通模型作为属性传递,不如从普通模型中获取他们需要的点点滴滴,然后将它们放入视图中(即:您可能只需要普通模型中的一半属性位于视图模型中)。这是因为,请记住,视图模型将被传递给视图,并且他们不想传递他们不会使用的东西:)。但这意味着您最有可能需要一个一个地设置这些属性(除非这些确切的属性被封装在一个通常不会偶然发生的子类中,哈哈)。

    为了简单起见,我将它保存在一个镜头中,这样您就可以一次性复制正常模型。

    现在,当您将视图模型传递给您的视图 (MyViewModel) 时,您将能够通过对象表示法及其属性使用和访问普通模型,例如... Model.MyNormalModel.Property1。等等,并在视图中用它做任何你想做的事情......此外,您可以像这样访问视图模型的其余部分(我们设置的 const 值)...... Model.MyPathConstant1 和 Model.MyPathConstant2 等等......所以您几乎可以访问您想要的所有内容,您的普通模型以及您稍后通过现在称为视图模型添加的任何其他内容。

    请原谅拼写错误 - 来自 ipad 的写作,哈哈。让我知道这是否更有意义。

    【讨论】:

    • 谢谢,这似乎是个不错的建议!只有当您能更清楚地了解如何在一处修改 ViewModel 时?我有一个BaseController 类,在它的构造函数中做一些魔术就足够了吗?我绝对想避免在每个动作中都必须做某事(这只会将原来的问题转移到其他地方)。
    • 好的,我现在将更新我的答案...基本上,您手动创建视图模型并为您的普通模型包含一个属性,然后在视图模型中包含您上面提到的属性以及所有一个地方......所以就像你用视图模型封装模型一样,这有意义吗?您为您的模型属性(类型为 YourModel)和您在您的视图模型中提到的所有值设置值。现在发布示例代码...
    • 好的,感谢您的建议。但是,如上所述,我提出了另一种选择,并且更喜欢沿着这条路走——在我看来,扩展 UrlHelper 是正确的做法,因为它与路径有关,并且任何进行路径管理的任务都应该真正属于它的集合职责而不是模块'/页面'。
    【解决方案6】:

    您可以使用 UrlHelper Content 的内置属性:

    @Url.Content("~/Content/Stylsheets")
    @Url.Content("~/Content/Images")
    

    【讨论】:

    • 是的,除了我想在一个地方定义“~/Content/Stylesheets”,这样当我的文件夹结构发生一点变化时,我就不用回去到处更改路径了我使用图像、样式或脚本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-10
    • 1970-01-01
    • 2012-01-09
    • 2014-02-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多