"proper"MVC怎么做?
How to do "proper" MVC?
我是一名新的网络开发人员(约 1 年经验),刚刚加入一家新公司,该公司在我们开发的许多网站中使用 Umbraco CMS。在我上一份工作中,我只接触过 WebForms,所以在开始这份工作之前我对 MVC 做了一些研究,并做了一个非常初学者的教程,但我不确定我是否理解社区的 "best practices" 当它出现时对于这些东西,希望你们能帮助我。当谈到 Umbraco CMS 时,有一些名为 "Macro-Scripts" 的组件,它本质上是一个 Razor View (.CSHTML),它允许您在页面中编写一堆 C# 和 HTML并在您选择的任何 CMS 页面上显示此 "Macro-Script"。
在我的教程(我在 2 个多月前完成)中,我想我记得读过一些关于永远不要将条件逻辑/C# 与 HTML 混合的内容,并且使用模型和控制器更好?我有点困惑,因为我们一开始并没有真正为我们的网站构建控制器,因为它们是 CMS 页面,如果它们需要除 Rich-Text 之外的任何内容,那么我们只需创建一个 "Macro-Script" 并放置它在需要扩展功能的页面上。
我在这里工作的第一个月发现,如果我能够让我的代码在整个网站上重复使用,我可以节省很多时间,但我不太确定如何做到以 "MVC friendly" 的方式做到这一点?这是一个示例 "Macro-Script",它显示在 CMS 中创建的表单,然后尝试获取公司 "contact" 信息并将其显示在表单下方。我所附的示例非常简单,但我看到的这些宏脚本中有一些变成了 500 多行的残忍混乱,其中包含巨大的 for-each 循环、开关和不可读的代码块。
是否可以将此类代码拆分为模型以供此视图使用?与将所有代码都放在同一个视图中相比,拆分代码有什么好处吗? (如果有足够的好处,我想将其展示给我的同事并更改编码标准)。有人可以给我举个例子,说明如果将其拆分为适当的 "MVC" 会是什么样子吗?如果这不是 post 此类问题的正确位置,请向我指出更好的 StackExchange 站点。谢谢
获取 CMS 表单和公司信息的宏脚本
@inherits umbraco.MacroEngines.DynamicNodeContext
@*
Model = The current page the macro is executed on
@Model.bodyText
Parameter = collection of parameter values passed from the macro
@Paramter.myParam
Library = utillity library with common methods
@Library.NodeById(1233)
*@
@* The fun starts here *@
@{
string formClass = "form-content";
var configNode = Model.AncestorOrSelf().Descendants("ConfigurationContainer").FirstOrDefault();
if (configNode != null && configNode.Id > 0)
{
formClass = "form-content show-address";
}
if (custom.Library.NodeHasPropertyAndValue(Model, "bodyText"))
{
<hr />
}
<div class="form-page contact-us">
<div>
<div class="@formClass">
@Html.Raw(umbraco.library.RenderMacroContent("<?UMBRACO_MACRO macroAlias=\"umbracoContour.RazorRenderForm\" formGuid=\""+Model.selectedForm+"\" ></?UMBRACO_MACRO>", Model.Id))
</div>
@if (configNode != null && configNode.Id > 0)
{
<address class="address-content">
@if (custom.Library.NodeHasPropertyAndValue(configNode, "officeAddress"))
{
var addressDisplay = (custom.Library.NodeHasPropertyAndValue(configNode, "officeAddress2")) ? string.Format("{0}, {1}", configNode.officeAddress, configNode.officeAddress2) : configNode.officeAddress;
string locationString = string.Empty;
string cityDisplay = (custom.Library.NodeHasPropertyAndValue(configNode, "officeCity")) ? configNode.officeCity : string.Empty,
stateDisplay = (custom.Library.NodeHasPropertyAndValue(configNode, "officeState")) ? configNode.officeState : string.Empty,
zipDisplay = (custom.Library.NodeHasPropertyAndValue(configNode, "officeZip")) ? configNode.officeZip : string.Empty;
if (!string.IsNullOrEmpty(cityDisplay) && !string.IsNullOrEmpty(stateDisplay))
{
locationString = string.Format("<br />{0}, {1} {2}", cityDisplay, stateDisplay, zipDisplay);
}
@addressDisplay@Html.Raw(locationString)
}
@if (custom.Library.NodeHasPropertyAndValue(configNode, "officePhone"))
{
<br /><i class="fa fa-phone"></i> @configNode.officePhone
}
@if (custom.Library.NodeHasPropertyAndValue(configNode, "officeFax"))
{
<br /><i class="fa fa-fax"></i> @configNode.officeFax
}
@if (custom.Library.NodeHasPropertyAndValue(configNode, "officeEmail"))
{
<br /><i class="fa fa-envelope"></i> <a href="mailto:@configNode.officeEmail">@configNode.officeEmail</a>
}
</address>
}
</div>
</div>
if (custom.Library.NodeHasPropertyAndValue(Model, "lowerText"))
{
@Html.Raw(Model.lowerText)
}
}
我将在这里使用 Umbraco 术语,乍一看可能不像 Asp.Net MVC:
你需要问问自己——你需要使用宏吗?如果您将宏直接嵌入到模板中,那么您可以使用 PartialView(在 /Views/Partials 中找到,就像标准 MVC 一样)或者直接将布局合并到模板中(在 /Views 中找到) .
您应该做的第一件事是查看 Umbraco 文档(记下每个主题针对的 Umbraco 版本 - 那里仍然有 Umbraco 4.10+ 特定内容):
https://our.umbraco.org/documentation/Reference/Templating/
关于拆分逻辑:
Code First 模型:
看看 Umbraco Ditto - 这是一种将模型与 Umbraco IPublishedContent 一起使用的方法;有相当多的文档,所以它应该很容易实现。
控制器:
您可以使用 ASP.Net MVC 控制器来支持您的部分并提供模型;你需要从 SurfaceControllers
继承:
https://our.umbraco.org/documentation/Reference/Routing/surface-controllers
渲染宏:不要使用@Html.Raw(umbraco.library.RenderMacroContent(..))
- 它几乎已被弃用。现在标准的做法是使用@Umbraco.RenderMacro()
。所以这个:
@Html.Raw(umbraco.library.RenderMacroContent("<?UMBRACO_MACRO macroAlias=\"umbracoContour.RazorRenderForm\" formGuid=\""+Model.selectedForm+"\" ></?UMBRACO_MACRO>", Model.Id))
变成
@Umbraco.RenderMacro("FormsRenderForm", new { FormGuid = Model.selectedForm })
最后的想法:
就个人而言,我不会使用宏来生成您的内容,除非您需要允许后台用户将功能嵌入到页面中并提供参数。如果不是这种情况,您最好直接在模板或局部视图中实现布局。
我是一名新的网络开发人员(约 1 年经验),刚刚加入一家新公司,该公司在我们开发的许多网站中使用 Umbraco CMS。在我上一份工作中,我只接触过 WebForms,所以在开始这份工作之前我对 MVC 做了一些研究,并做了一个非常初学者的教程,但我不确定我是否理解社区的 "best practices" 当它出现时对于这些东西,希望你们能帮助我。当谈到 Umbraco CMS 时,有一些名为 "Macro-Scripts" 的组件,它本质上是一个 Razor View (.CSHTML),它允许您在页面中编写一堆 C# 和 HTML并在您选择的任何 CMS 页面上显示此 "Macro-Script"。
在我的教程(我在 2 个多月前完成)中,我想我记得读过一些关于永远不要将条件逻辑/C# 与 HTML 混合的内容,并且使用模型和控制器更好?我有点困惑,因为我们一开始并没有真正为我们的网站构建控制器,因为它们是 CMS 页面,如果它们需要除 Rich-Text 之外的任何内容,那么我们只需创建一个 "Macro-Script" 并放置它在需要扩展功能的页面上。
我在这里工作的第一个月发现,如果我能够让我的代码在整个网站上重复使用,我可以节省很多时间,但我不太确定如何做到以 "MVC friendly" 的方式做到这一点?这是一个示例 "Macro-Script",它显示在 CMS 中创建的表单,然后尝试获取公司 "contact" 信息并将其显示在表单下方。我所附的示例非常简单,但我看到的这些宏脚本中有一些变成了 500 多行的残忍混乱,其中包含巨大的 for-each 循环、开关和不可读的代码块。
是否可以将此类代码拆分为模型以供此视图使用?与将所有代码都放在同一个视图中相比,拆分代码有什么好处吗? (如果有足够的好处,我想将其展示给我的同事并更改编码标准)。有人可以给我举个例子,说明如果将其拆分为适当的 "MVC" 会是什么样子吗?如果这不是 post 此类问题的正确位置,请向我指出更好的 StackExchange 站点。谢谢
获取 CMS 表单和公司信息的宏脚本
@inherits umbraco.MacroEngines.DynamicNodeContext
@*
Model = The current page the macro is executed on
@Model.bodyText
Parameter = collection of parameter values passed from the macro
@Paramter.myParam
Library = utillity library with common methods
@Library.NodeById(1233)
*@
@* The fun starts here *@
@{
string formClass = "form-content";
var configNode = Model.AncestorOrSelf().Descendants("ConfigurationContainer").FirstOrDefault();
if (configNode != null && configNode.Id > 0)
{
formClass = "form-content show-address";
}
if (custom.Library.NodeHasPropertyAndValue(Model, "bodyText"))
{
<hr />
}
<div class="form-page contact-us">
<div>
<div class="@formClass">
@Html.Raw(umbraco.library.RenderMacroContent("<?UMBRACO_MACRO macroAlias=\"umbracoContour.RazorRenderForm\" formGuid=\""+Model.selectedForm+"\" ></?UMBRACO_MACRO>", Model.Id))
</div>
@if (configNode != null && configNode.Id > 0)
{
<address class="address-content">
@if (custom.Library.NodeHasPropertyAndValue(configNode, "officeAddress"))
{
var addressDisplay = (custom.Library.NodeHasPropertyAndValue(configNode, "officeAddress2")) ? string.Format("{0}, {1}", configNode.officeAddress, configNode.officeAddress2) : configNode.officeAddress;
string locationString = string.Empty;
string cityDisplay = (custom.Library.NodeHasPropertyAndValue(configNode, "officeCity")) ? configNode.officeCity : string.Empty,
stateDisplay = (custom.Library.NodeHasPropertyAndValue(configNode, "officeState")) ? configNode.officeState : string.Empty,
zipDisplay = (custom.Library.NodeHasPropertyAndValue(configNode, "officeZip")) ? configNode.officeZip : string.Empty;
if (!string.IsNullOrEmpty(cityDisplay) && !string.IsNullOrEmpty(stateDisplay))
{
locationString = string.Format("<br />{0}, {1} {2}", cityDisplay, stateDisplay, zipDisplay);
}
@addressDisplay@Html.Raw(locationString)
}
@if (custom.Library.NodeHasPropertyAndValue(configNode, "officePhone"))
{
<br /><i class="fa fa-phone"></i> @configNode.officePhone
}
@if (custom.Library.NodeHasPropertyAndValue(configNode, "officeFax"))
{
<br /><i class="fa fa-fax"></i> @configNode.officeFax
}
@if (custom.Library.NodeHasPropertyAndValue(configNode, "officeEmail"))
{
<br /><i class="fa fa-envelope"></i> <a href="mailto:@configNode.officeEmail">@configNode.officeEmail</a>
}
</address>
}
</div>
</div>
if (custom.Library.NodeHasPropertyAndValue(Model, "lowerText"))
{
@Html.Raw(Model.lowerText)
}
}
我将在这里使用 Umbraco 术语,乍一看可能不像 Asp.Net MVC:
你需要问问自己——你需要使用宏吗?如果您将宏直接嵌入到模板中,那么您可以使用 PartialView(在 /Views/Partials 中找到,就像标准 MVC 一样)或者直接将布局合并到模板中(在 /Views 中找到) .
您应该做的第一件事是查看 Umbraco 文档(记下每个主题针对的 Umbraco 版本 - 那里仍然有 Umbraco 4.10+ 特定内容):
https://our.umbraco.org/documentation/Reference/Templating/
关于拆分逻辑:
Code First 模型: 看看 Umbraco Ditto - 这是一种将模型与 Umbraco IPublishedContent 一起使用的方法;有相当多的文档,所以它应该很容易实现。
控制器:
您可以使用 ASP.Net MVC 控制器来支持您的部分并提供模型;你需要从 SurfaceControllers
继承:
https://our.umbraco.org/documentation/Reference/Routing/surface-controllers
渲染宏:不要使用@Html.Raw(umbraco.library.RenderMacroContent(..))
- 它几乎已被弃用。现在标准的做法是使用@Umbraco.RenderMacro()
。所以这个:
@Html.Raw(umbraco.library.RenderMacroContent("<?UMBRACO_MACRO macroAlias=\"umbracoContour.RazorRenderForm\" formGuid=\""+Model.selectedForm+"\" ></?UMBRACO_MACRO>", Model.Id))
变成
@Umbraco.RenderMacro("FormsRenderForm", new { FormGuid = Model.selectedForm })
最后的想法:
就个人而言,我不会使用宏来生成您的内容,除非您需要允许后台用户将功能嵌入到页面中并提供参数。如果不是这种情况,您最好直接在模板或局部视图中实现布局。