问题
I've just updated my Visual Studio 2017 ASP.NET MVC 5 application from Bootstrap v3 to v4. I'm finding when I add a new edit partial view using scaffolding, it is still using the Bootstrap v3 CSS class names for the form. Is there a way to update the scaffolding to use BS v4?
Edit
There seems to be some confusion about what I'm talking about.
In Visual Studio 2017, in an MVC project, in Solution Explorer, right click the Views folder > Add > View... > MVC 5 View > Click Add
.
This brings up the Add View dialog. I type my View name, choose the Edit Template and choose, for this example, LoginVm
as the Model class. Visual Studio generates this markup. This process is called scaffolding.
@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>
Notice the Bootstrap 3 classes in use such as form-label
and col-md-offset-2
. These were removed in Bootstrap 4. Similarly, if you were to create a new Layout page, it would generate a Bootstrap 3 Navbar which is invalid in Bootstrap 4.
So I'm asking if there is a way (short of writing a custom scaffolder) to update Visual Studio to stop outputting Bootstrap 3 specific markup and, ideally, output Bootstrap 4 markup instead?
回答1:
The templates used by the scaffolding engine in VS are fixed. They are located in your VS install dir (e.g. %programfiles%\Microsoft Visual Studio\2017\Community\Common7\IDE\Extensions\Microsoft\Web\Mvc\Scaffolding\Templates\MvcView).
So the Bootstrap 3 classes are fixed in the T4-files provided by MS (current standard is BS3 which is added by default currently when creating a new MVC web project). Just have a look at "Edit.cs.t4" in the dir mentioned above. You will find deprecated BS3 classes like "btn-default" (which is btn-secondary in BS4) in there.
You can create your own custom T4-templates if you like. The MS ref for this task would be: https://docs.microsoft.com/en-us/visualstudio/modeling/code-generation-and-t4-text-templates
回答2:
An update is not yet available, however to support the edit view scaffolding with Bootstrap 4 in Visual Studio 2017, You have to edit the file Edit.cs.t4 in "%ProgramFiles%\Microsoft Visual Studio\2017\Community\Common7\IDE\Extensions\Microsoft\Web\Mvc\Scaffolding\Templates\MvcView"
- Rename the file to "Edit.cs.backup.t4"
- Create a new file "Edit.cs.t4" and add the following code, this will support new Bootstrap 4 classes and form controls (Bootstrap custom forms and controls):
<#@ 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" #>
来源:https://stackoverflow.com/questions/49639302/update-visual-studio-2017-mvc-view-scaffolding-to-bootstrap-4