更新Visual Studio 2017 MVC视图脚手架为Bootstrap 4



我刚刚更新了Visual Studio 2017 ASP.NET MVC 5应用程序从Bootstrap V3到V4。我发现,当我使用脚手架添加新的编辑部分视图时,它仍在使用Bootstrap V3 CSS类名称。有没有办法更新脚手架以使用BS V4?

编辑

似乎对我在说什么感到有些困惑。

在Visual Studio 2017中,在MVC项目中,在解决方案资源管理器中,右键单击Views folder > Add > View... > MVC 5 View > Click Add

这将提出"添加视图"对话框。我输入视图名称,选择编辑模板,然后选择此示例,将LoginVm作为模型类。Visual Studio生成此标记。此过程称为脚手架。

@model Demo.ViewModels.LoginVm
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    <div class="form-horizontal">
        <h4>LoginVm</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.UserName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.UserName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.UserName, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.Password, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Password, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Password, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>

请注意使用中的Bootstrap 3类,例如form-labelcol-md-offset-2。同样,在Bootstrap4中删除了这些内容。如果要创建一个新的布局页面,它将生成一个Bootstrap 3 Navbar,该页面在Bootstrap 4中无效。

所以我问是否有一种方法(写自定义脚手架(来更新Visual Studio,以停止输出Bootstrap 3特定的标记,理想情况下,输出Bootstrap 4标记?

尚不可用,但是要支持Visual Studio 2017中使用Bootstrap 4的编辑视图脚手架,您必须在"%programFiles% in Visual Studio 2017中编辑文件edit.cs.t4Microsoft Visual Studio 2017 community common7 iDe Extensions Microsoft Microsoft Web mvc capfolding spaffates spemplates mvcview"

  • 将文件重命名为" edit.cs.backup.t4"
  • 创建一个新的文件" edit.cs.t4"并添加以下代码,这将支持新的Bootstrap 4类和表单控件(Bootstrap自定义表单和控件(:

<#@ template language="C#" HostSpecific="True" #>
<#@ output extension=".cshtml" #>
<#@ include file="Imports.include.t4" #>
@model <#= ViewDataTypeName #>
<#
// "form-control" attribute is only supported for all EditorFor() in System.Web.Mvc 5.1.0.0 or later versions, except for checkbox, which uses a div in Bootstrap
string boolType = "System.Boolean";
Version requiredMvcVersion = new Version("5.1.0.0");
bool isControlHtmlAttributesSupported = MvcVersion >= requiredMvcVersion;
// The following chained if-statement outputs the file header code and markup for a partial view, a view using a layout page, or a regular view.
if(IsPartialView) {
#>
<#
} else if(IsLayoutPageSelected) {
#>
@{
    ViewBag.Title = "<#= ViewName#>";
<#
if (!String.IsNullOrEmpty(LayoutPageFile)) {
#>
    Layout = "<#= LayoutPageFile#>";
<#
}
#>
}
<h2><#= ViewName#></h2>
<#
} else {
#>
@{
    Layout = null;
}
<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title><#= ViewName #></title>
</head>
<body>
<#
    PushIndent("    ");
}
#>
<#
if (ReferenceScriptLibraries) {
#>
<#
    if (!IsLayoutPageSelected && IsBundleConfigPresent) {
#>
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryval")
<#
    }
#>
<#
    else if (!IsLayoutPageSelected) {
#>
<script src="~/Scripts/jquery-<#= JQueryVersion #>.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
<#
    }
#>
<#
}
#>
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    
    
        <h4><#= ViewDataTypeShortName #></h4>
        <hr />
<# 
    if (isControlHtmlAttributesSupported) {
#>
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
<#        
    } else {
#>
        @Html.ValidationSummary(true)
<#      
    }
#>
<#
foreach (PropertyMetadata property in ModelMetadata.Properties) {
    if (property.Scaffold && !property.IsAssociation) {
        if (property.IsPrimaryKey) {
#>
        @Html.HiddenFor(model => model.<#= property.PropertyName #>)
<#
        } else if (!property.IsReadOnly) {
			bool isCheckbox = property.TypeName.Equals(boolType);
#>
        <div class="form-group">
<#
            if (property.IsForeignKey) {
#>
            @Html.LabelFor(model => model.<#= property.PropertyName #>, "<#= GetAssociationName(property) #>", htmlAttributes: new { @class = "col-form-label col-lg-2" })
<#
            } else if (!isCheckbox) {			
#>
            @Html.LabelFor(model => model.<#= property.PropertyName #>, htmlAttributes: new { @class = "col-form-label col-lg-2" })
<#
            }
#>
            <div class="col-lg-10">
<#
            
            if (property.IsForeignKey) {
#>
<# 
            if (isControlHtmlAttributesSupported) {
#>
                @Html.DropDownList("<#= property.PropertyName #>", null, htmlAttributes: new { @class = "form-control" })
<#
            } else {
#>
                @Html.DropDownList("<#= property.PropertyName #>", String.Empty)
<#
            }
#>
<#
            } else  if (isControlHtmlAttributesSupported) {
                if (isCheckbox) {
#>
                <div class="custom-control custom-checkbox">
<#
                    PushIndent("    ");
#>
                @Html.EditorFor(model => model.<#= property.PropertyName #>, new { htmlAttributes = new { @class = "custom-control-input" } })
				@Html.LabelFor(model => model.<#= property.PropertyName #>, htmlAttributes: new { @class = "custom-control-label" })
<#
                } else if (property.IsEnum && !property.IsEnumFlags) {
#>
                @Html.EnumDropDownListFor(model => model.<#= property.PropertyName #>, htmlAttributes: new { @class = "form-control" })
<#
                } else {
#>
                @Html.EditorFor(model => model.<#= property.PropertyName #>, new { htmlAttributes = new { @class = "form-control" } })
<#
                }
            } else {
#>
                @Html.EditorFor(model => model.<#= property.PropertyName #>)
<#
            }
#>
<# 
            if (isControlHtmlAttributesSupported) {
#>
                @Html.ValidationMessageFor(model => model.<#= property.PropertyName #>, "", new { @class = "text-danger" })
<#        
            } else {
#>
                @Html.ValidationMessageFor(model => model.<#= property.PropertyName #>)
<#      
            }
#>
<#
            if (isCheckbox && isControlHtmlAttributesSupported) {
                PopIndent();
#>
                </div>
<#
            }
#>
            </div>
        </div>
<#
        }
    }
}
#>
        <div class="form-group">
			<div class="col-lg-10">
				<input type="submit" value="Save" class="btn btn-primary">
			</div>
		</div>
    
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>
<#
if(IsLayoutPageSelected && ReferenceScriptLibraries && IsBundleConfigPresent) {
#>
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}
<#
}
#>
<#
else if(IsLayoutPageSelected && ReferenceScriptLibraries) {
#>
<script src="~/Scripts/jquery-<#= JQueryVersion #>.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
<#
}
#>
<#
// The following code closes the tag used in the case of a view using a layout page and the body and html tags in the case of a regular view page
#>
<#
if(!IsPartialView && !IsLayoutPageSelected) {
    ClearIndent();
#>
</body>
</html>
<#
}
#>
<#@ include file="ModelMetadataFunctions.cs.include.t4" #>

vs中脚手架引擎使用的模板是固定的。它们位于您的VS安装DIR中(例如%programFiles% Microsoft Visual Studio 2017 community commone common7 inide extensions Microsoft Microsoft Web mvc mvc cackoffates spegolding templates mvcview(。

因此,Bootstrap 3类是在MS提供的T4文件中固定的(当前标准为BS3,默认情况下在创建新的MVC Web项目时默认添加(。只需在上面提到的DIR中查看" edit.cs.t4"即可。您会在其中找到" btn-default"(在bs4中的BTN默认(等弃用的BS3类。

如果您愿意,您可以创建自己的自定义T4-TEMPLATE。此任务的MS Ref将是:https://learn.microsoft.com/en-us/visalstudio/modeling/code-generation/code-generation-and-t4-text-templates

要修复/更新ASP .NET MVC 5项目Navbar到Bootstrap 4您必须手动更新代码:

  • 视图 ->共享 -> _layout.cshtml。

<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
  <div class="container">
    @Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
    <button type="button" class="navbar-toggler" data-toggle="collapse" data-target=".navbar-collapse" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="navbar-collapse collapse">
      <ul class="nav navbar-nav mr-auto">
          <li class="nav-item">@Html.ActionLink("Home", "Index", "Home", null, new { @class = "nav-link" })</li>
          <li class="nav-item">@Html.ActionLink("About", "About", "Home", null, new { @class = "nav-link" })</li>
          <li class="nav-item">@Html.ActionLink("Contact", "Contact", "Home", null, new { @class = "nav-link" })</li>
      </ul>
      @Html.Partial("_LoginPartial")
    </div>
  </div>
</nav>

然后,如果您不使用登录部分,则可以将其删除。否则,将_loginpartial.cshtml更改为:

@using Microsoft.AspNet.Identity
@if (Request.IsAuthenticated)
{
  using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm" }))
  {
  @Html.AntiForgeryToken()
  <ul class="nav navbar-nav">
    <li class="nav-item">
        @Html.ActionLink("Hello " + User.Identity.GetUserName() + "!", "Index", "Manage", routeValues: null, htmlAttributes: new { title = "Manage", @class = "nav-link" })
    </li>
    <li class="nav-item"><a class="nav-link" href="javascript:document.getElementById('logoutForm').submit()">Log off</a></li>
  </ul>
  }
}
else
{
  <ul class="nav navbar-nav">
    <li class="nav-item">@Html.ActionLink("Register", "Register", "Account", routeValues: null, htmlAttributes: new { id = "registerLink", @class = "nav-link" })</li>
    <li class="nav-item">@Html.ActionLink("Log in", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink", @class = "nav-link" })</li>
  </ul>
}

和最后一次从content/site.css中删除下一行:

/*delete this*/
body {
    padding-top: 50px;
    padding-bottom: 20px;
}

最新更新